February 05, 2010
by ton_mit
|
Hello all again...I am trying to program multi array with spi and am having trouble.................with the programs from(ledarray_spi)master, slave and extras I downloaded from nerdkits all I have changed is the number of arrays.I have built and flashed the Atmega 328p's master and slave controllers and wired only one array until I get the programing down. When I turn it on a question mark (?) will scroll across the array then nothing else. Is this normal for not being hooked up to a stream? If so.....that will mean that I actually built it right(the first time) and I can proceed.
What I really want is to have a character string that can be edited to say "whatever I want" like I did with just the single led array I have been working on.
I am learning C through Nerdkits and am loving all the projects they
have to offer. I know Basic, QBasic, Visual Basic but its been a while.
Here is the code that I used for the single array build. How do I
integrate this into the ledarray_spi master and slave programs? btw all
of the Atmega 328p's that I use were preloaded and purchased from
nerdkits and I am using Programers Notepad.
// This program will make text scroll
//atmega328p
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/io_328p.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 F_CPU 14745600
#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));
}
}
}
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 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 scroll_display(const char *s) {
// clear display
ledarray_blank();
int8_t offset = 0 , next_offset = 0;
uint8_t is_started = 0;
uint8_t i=0;
char x=' ';
// 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(90);
// 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(90);
ledarray_left_shift();
if(next_offset > 0) {
offset -= 1;
next_offset -= 1;
}
font_display(x, offset);
}
delay_ms(90);
// this final loop shifts the display all the way off.
for(i=0;i<COLS;i++){
ledarray_left_shift();
delay_ms(90);
}
return;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
int main() {
ledarray_init();
// activate interrupts
sei();
uint8_t i, j;
while(1)
for(i=0;i<ROWS;i++) {
for(j=0;j<COLS;j++) {
ledarray_set(i,j, 0);
delay_ms(30);
}
scroll_display(PSTR("WHATEVER I WANT"));
}
for(i=0;i<ROWS;i++) {
for(j=0;j<COLS;j++) {
ledarray_set(i,j, 0);
delay_ms(30);
return(0);
}
}
}
|