October 25, 2011
by Gianni
|
Rick, I finally got back to this, but am having trouble getting your code to run. Can you or anyone else give me a pointer to how to go from copying your chunk of code to running it? While I'd like to go through and learn from the beginning, I'd also like to just mod your code for the time being.
I can get the ledarray.c to load in the ledarray_template folder, and just tried to replace the code in the ledarray.c file with yours, save, and run the make file, but the command window says:
make -C ../libnerdkits
make: *** ../libnerdkits: No such file or directory. Stop.
make: *** [ledarray.hex] Error 2
I know the above isn't code but I indented it so it's easier to read. The code of your's I'm referring to is:
// ledarray.c
// for NerdKits with ATmega168
// mrobbins@mit.edu
// Modified by Rick Shear
#define F_CPU 14745600
#include "../libnerdkits/io_328p.h"
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
// #include "../libnerdkits/uart.h"
#include "font.h"
// PIN DEFINITIONS:
//
// PB1-5 ROW DRIVERS (0-4)
// PC0-5,PD2-7: COLUMN DRIVERS (0-11)
#define ROWS 5
#define COLS 24
volatile uint8_t la_row, real_row;
volatile uint8_t la_data[COLS];
inline uint8_t ledarray_get(uint8_t i, uint8_t j) {
if(i < ROWS && j < COLS) {
if((la_data[j] & (1<<i)) != 0) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
inline void ledarray_set(uint8_t i, uint8_t j, uint8_t onoff) {
if(i < ROWS && j < COLS) {
if(onoff) {
la_data[j] |= (1<<i);
} else {
la_data[j] &= ~(1<<i);
}
}
}
inline void ledarray_set_columndriver(uint8_t j, uint8_t onoff, uint8_t sense) {
// cols 0-5: PC0-5
// cols 6-11: PD2-7
if(j < 6) {
if(onoff) {
PORTC |= (1 << (PC0 + j));
} else {
PORTC &= ~(1<< (PC0 + j));
}
if(sense == onoff) {
DDRC |= (1 << (PC0 + j));
} else {
DDRC &= ~(1 << (PC0 + j));
PORTC &= ~(1 << (PC0 + j));
}
} else {
if(onoff) {
PORTD |= (1 << (PD2 + (j-6)));
} else {
PORTD &= ~(1<< (PD2 + (j-6)));
}
if(sense == onoff) {
DDRD |= (1 << (PD2 + (j-6)));
} else {
DDRD &= ~(1 << (PD2 + (j-6)));
PORTD &= ~(1 << (PD2 + (j-6)));
}
}
}
inline void ledarray_all_off() {
// turn off all row drivers
DDRB &= ~( (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5) );
PORTB &= ~( (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5) );
// turn off all column drivers
DDRC &= ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) );
PORTC &= ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) );
DDRD &= ~( (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7) );
PORTD &= ~( (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7) );
}
ISR(TIMER0_OVF_vect) {
// turn off old row driver
DDRB &= ~(1 << (PB1 + real_row));
PORTB &= ~(1 << (PB1 + real_row));
ledarray_all_off();
// increment row number
if(++la_row == 2*ROWS)
la_row = 0;
// set column drivers appropriately
uint8_t j;
if(la_row%2 == 0) {
// even la_row number: fill even columns
real_row = la_row / 2;
for(j=0; j<COLS/2; j++) {
ledarray_set_columndriver(j, ledarray_get(real_row, 2*j), 1);
}
// activate row driver SINK
PORTB &= ~(1 << (PB1 + real_row));
DDRB |= (1 << (PB1 + real_row));
} else {
// odd la_row number: fill odd columns
real_row = (la_row-1)/2;
for(j=0; j<COLS/2; j++) {
ledarray_set_columndriver(j, 1 - ledarray_get(real_row, 2*j + 1), 0);
}
// activate row driver SOURCE
PORTB |= (1 << (PB1 + real_row));
DDRB |= (1 << (PB1 + real_row));
}
}
void ledarray_init() {
// Timer0 CK/64 (900Hz)
TCCR0B = (1<<CS01) | (1<<CS00);
TIMSK0 = (1<<TOIE0);
// outputs (set row drivers high for off)
DDRC &= ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5) );
DDRD &= ~( (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7) );
DDRB &= ~( (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5) );
}
void ledarray_left_shift() {
// shift everything one position left
uint8_t i, j;
for(i=0; i<ROWS; i++) {
for(j=0; j<COLS-1; j++) {
ledarray_set(i,j, ledarray_get(i, j+1));
}
ledarray_set(i,23,0);
}
}
void ledarray_right_shift(){
// shift everything right one position
uint8_t i, j;
for(i=0; i<ROWS; i++) {
for(j=COLS-1; j>0; j--) {
ledarray_set(i,j, ledarray_get(i, j-1));
}
ledarray_set(i,0,0);
}
}
void ledarray_shift_up(){
// shift everything up one position
uint8_t i,j;
for(i=0;i<ROWS-1;i++){
for(j=0;j<COLS;j++){
ledarray_set(i,j,ledarray_get(i+1,j));
}
}
// blank bottom line to prevent 'smearing'
for(j=0;j<COLS;j++){
ledarray_set(4,j,0);
}
}
void ledarray_shift_down(){
// shift everything down one position
uint8_t i,j;
for(i=4;i>0;i--){
for(j=0;j<COLS;j++){
ledarray_set(i,j,ledarray_get(i-1,j));
}
}
// blank top line to prevent 'smearing'
for(j=0;j<COLS;j++){
ledarray_set(0,j,0);
}
}
void ledarray_blank() {
uint8_t i, j;
for(i=0; i<ROWS; i++) {
for(j=0; j<COLS; j++) {
ledarray_set(i,j,0);
}
}
}
void ledarray_testpattern() {
uint8_t i, j, ct;
ledarray_blank();
// set initital pattern (every other LED on)
for(i=0;i<ROWS;i++) {
for(j=i%2;j<COLS;j += 2) {
ledarray_set(i,j, 1 - ledarray_get(i,j));
}
}
//wait 50ms
delay_ms(50);
// toggle the pattern turning what was on off then back on again 10 times
for(ct=0;ct<10;ct++){
for(i=0;i<ROWS;i++) {
for(j=0;j<COLS;j++) {
ledarray_set(i,j, 1 - ledarray_get(i,j));
}
}
delay_ms(50);
for(i=0;i<ROWS;i++) {
for(j=0;j<COLS;j++){
ledarray_set(i,j, 1 - ledarray_get(i,j));
}
}
delay_ms(50);
}
}
void font_get(char match, char *buf) {
// copies the character "match" into the buffer
uint8_t i;
PGM_P p;
for(i=0; i<FONT_SIZE; i++) {
memcpy_P(&p, &font[i], sizeof(PGM_P));
if(memcmp_P(&match, p,1)==0) {
memcpy_P(buf, p, 7);
return;
}
}
// NO MATCH?
font_get('?', buf);
}
uint8_t font_width(char c) {
char buf[7];
buf[1] = 0;
font_get(c, buf);
return buf[1];
}
void font_display(char c, uint8_t offset) {
char buf[7];
font_get(c, buf);
uint8_t width = buf[1];
uint8_t i, j;
for(i=0; i<ROWS; i++) {
for(j=0; j<width; j++) {
if((offset + j) < COLS) {
if( (buf[2+j] & (1<<i)) != 0) {
ledarray_set(i,offset + j,1);
} else {
ledarray_set(i,offset + j,0);
}
}
}
}
// blank the next column to the right
for(i=0; i<ROWS; i++) {
ledarray_set(i, offset+width, 0);
}
}
void font_display_ud(char c, uint8_t offset, uint8_t up) {
char buf[7];
// get font data for the current character and place it into the buffer
font_get(c, buf);
uint8_t width = buf[1];
uint8_t i, j, s,n;
if(up){
for(i=0; i<ROWS; i++) {
n=0;
s=4-i;
while(s<ROWS){
for(j=0; j<width; j++) {
if((offset + j) < COLS) {
if( (buf[2+j] & (1<<n)) != 0) {
ledarray_set(s,offset + j,1);
} else {
ledarray_set(s,offset + j,0);
}
}
}
delay_ms(7);
n++;
s++;
}
}
} else{
for(i=0; i<ROWS; i++) {
n=4-i;
s=0;
while(s<=i){
for(j=0; j<width; j++) {
if((offset + j) < COLS) {
if( (buf[2+j] & (1<<n)) != 0) {
ledarray_set(s,offset + j,1);
} else {
ledarray_set(s,offset + j,0);
}
}
}
delay_ms(7);
n++;
s++;
}
}
}
// blank the next column to the right
for(i=0; i<ROWS; i++) {
ledarray_set(i, offset+width, 0);
}
}
void scroll_display(const char *s,uint8_t speed) {
// clear display
ledarray_blank();
int8_t offset = 0 , next_offset = 0;
uint8_t is_started = 0;
uint8_t i=0;
char x=' ';
if(speed==0)
speed=90;
// begin loop and continue until nul character at end of string
while(pgm_read_byte(s) != 0x00){
// have we read a character?
if(is_started) {
// if so, place and shift the character until it is clear of column 24
while(next_offset>23){
delay_ms(speed);
// shift the display one place
ledarray_left_shift();
// check the end of the currently displayed characters if it's greater than zero, decrement
// both the offset (character display position), and next_offset(character end position)
if(next_offset > 0) {
offset -= 1;
next_offset -= 1;
}
// display the character at the new position
font_display(x, offset);
}
} else {
// if not, set offset to # of columns -1 (23)
offset = COLS-1;
}
// read the next character in the string
x = pgm_read_byte(s++);
// if we have already started, set the current display position to where the last character ended
if(is_started)
offset = next_offset;
// display the character
font_display(x, offset);
// create the new character end position
next_offset = offset + font_width(x)+1;
// set flag to show we have been through the loop
is_started = 1;
}
// Process the last character. This is neccessary since the while bails as soon as it reads
// the null character. At that point, the last read character has not yet shifted into full
// view. The following while loop shifts the final string character into full view.
while(next_offset>23){
delay_ms(speed);
ledarray_left_shift();
if(next_offset > 0) {
offset -= 1;
next_offset -= 1;
}
font_display(x, offset);
}
delay_ms(speed);
// this final loop shifts the display all the way off.
for(i=0;i<COLS;i++){
ledarray_left_shift();
delay_ms(speed);
}
return;
}
void do_testpattern() {
int8_t offset=0;
int8_t i=0;
while(1) {
//ledarray_testpattern();
ledarray_blank();
offset=0;
font_display_ud('H', 2,1); delay_ms(100);
font_display_ud('A', 6,0); delay_ms(100);
font_display_ud('P', 10,1); delay_ms(100);
offset=14;
font_display_ud('P', offset,0); offset += font_width('P')+1; delay_ms(100);
font_display_ud('Y', offset,1); offset += font_width('Y')+1; delay_ms(1500);
for(i=0;i<5;i++){
ledarray_shift_up();
delay_ms(80);
}
// for(i=0;i<COLS;i++){
// ledarray_left_shift();
// delay_ms(50);
//}
ledarray_blank();
scroll_display(PSTR("BIRTHDAY"),80);
ledarray_blank();
offset=1;
font_display_ud('D', offset,1); offset += font_width('D')+1; //delay_ms(1000);
font_display_ud('O', offset,1); offset += font_width('O')+1; //delay_ms(1000);
font_display_ud('N', offset,1); offset += font_width('N')+1; //delay_ms(1000);
font_display_ud('N', offset,1); offset += font_width('N')+1; //delay_ms(1000);
font_display_ud('A', offset,1); offset += font_width('A')+1; delay_ms(1500);
for(i=0;i<5;i++){
ledarray_shift_down();
delay_ms(80);
}
}
}
int main() {
ledarray_init();
// activate interrupts
sei();
/*
// init serial port
uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;
*/
// mode 1: test pattern
do_testpattern();
return 0;
}
|