working version

This commit is contained in:
Olaf Rempel 2012-02-07 20:45:45 +01:00
parent 72226b24a9
commit 5465febd59
1 changed files with 135 additions and 231 deletions

366
main.c
View File

@ -39,28 +39,22 @@
* PD2 -> /RX_TX * PD2 -> /RX_TX
* PD3 -> /LED * PD3 -> /LED
*/ */
#define TARGET_HW 1
#define ASM_IRQS 1
#if (TARGET_HW)
#define F_CPU 8000000 #define F_CPU 8000000
#else
#define F_CPU 7372800
#endif
#include <util/delay.h> #include <util/delay.h>
#define ROW1 PORTB3 #define ROW1 PORTB1 /* RED */
#define ROW2 PORTB2 #define ROW2 PORTB0 /* GREEN */
#define ROW3 PORTB1 #define ROW3 PORTB3 /* BLUE */
#define ROW4 PORTB0 #define ROW4 PORTB2 /* not used */
#define RXTX PORTD2 #define RXTX PORTD2
#define LED PORTD3 #define LED PORTD3
//#define BAUDRATE 115200 //#define BAUDRATE 115200
#if (!TARGET_HW) && (BAUDRATE) #if (BAUDRATE)
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1) #define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
static int uart_putchar(char c, FILE *stream) static int uart_putchar(char c, FILE *stream)
@ -76,28 +70,21 @@ static int uart_putchar(char c, FILE *stream)
} }
static FILE uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); static FILE uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
#endif /* (!TARGET_HW) && (BAUDRATE) */ #endif /* (BAUDRATE) */
static uint8_t valueR[16]; /* 16 values per color */
static uint8_t valueG[16]; static uint8_t chan_value[3][16];
static uint8_t valueB[16];
/* keep color in r4 */
register uint8_t nextColor asm("r4");
/* keep pointer in r2:r3 */
register uint8_t * pCurrentStep asm("r2");
/* 16 +1 * 4 values (portA, portC, OCR0, flags) per color */ /* 16 +1 * 4 values (portA, portC, OCR0, flags) per color */
static uint8_t data[17 * 4 * 3]; static uint8_t chan_rawdata[3][17 * 4];
/* offsets in data array */ /* used only in ISR */
#define RED_OFFSET (17 * 4 * 0) register uint8_t * pCurrentStep asm("r2"); /* r3:r2 */
#define GREEN_OFFSET (17 * 4 * 1)
#define BLUE_OFFSET (17 * 4 * 2)
/* used to sync ISR and color_update() */
register uint8_t nextColor asm("r4"); /* r4 */
#if ASM_IRQS /* worst case: 9+2+12+8+7+13 = 61 clks -> 7.625us @8MHz */
void __attribute__ ((naked)) SIG_OVERFLOW0 (void) void __attribute__ ((naked)) SIG_OVERFLOW0 (void)
{ {
asm volatile( asm volatile(
@ -111,59 +98,49 @@ void __attribute__ ((naked)) SIG_OVERFLOW0 (void)
); );
asm volatile( asm volatile(
"clr r24 \n\t" /* disable outputs 1+1 = 2 */
"out %0, r24 \n\t" /* PORTA = 0x00; */ "out %0, r1 \n\t" /* PORTA = 0x00; */
"out %1, r24 \n\t" /* PORTC = 0x00; */ "out %1, r1 \n\t" /* PORTC = 0x00; */
: :: "I" (_SFR_IO_ADDR(PORTA)),
: "I" (_SFR_IO_ADDR(PORTA)), "I" (_SFR_IO_ADDR(PORTC))
"I" (_SFR_IO_ADDR(PORTC))
); );
asm volatile( asm volatile(
/* switch color, assign pCurrentStep = data + RED/GREEN/BLUE_OFFSET */ /* switch color and assign pCurrentStep */
"mov r24, %0 \n\t" "mov r24, %0 \n\t" // 1 1 1
"inc %0 \n\t" /* nextColor++ */ "inc %0 \n\t" /* nextColor++ */ // 2 2 2
"cpi r24, 1 \n\t" "cpi r24, 1 \n\t" // 3 3 3
"brlo L_red%= \n\t" /* if (nextColor < 1) -> red */ "brlo L_red%= \n\t" /* if (nextColor < 1) -> red */ // 5 4 4
"breq L_green%= \n\t" /* if (nextColor == 1) -> green */ "breq L_green%= \n\t" /* if (nextColor == 1) -> green */ // - 6 5
"clr %0 \n\t" /* else set nextColor = 0, add BLUE_OFFSET */ "clr %0 \n\t" /* nextColor = 0; */ // - - 6
#if (TARGET_HW) "ldi r24, %8 \n\t" /* PORTB = (1<<ROW4); */ // - - 7
"ldi r24, 8 \n\t" "ldi r30, lo8(%4) \n\t" /* pCurrentStep = &rawdata[2]; */ // - - 8
"out %5, r24 \n\t" "ldi r31, hi8(%4) \n\t" // - - 9
#endif /* (TARGET_HW) */ "rjmp L_end%= \n\t" // - - 11
"ldi r24, %4 \n\t" "L_red%=: \n\t" /* red: */
"rjmp L_add%= \n\t" "ldi r24, %6 \n\t" /* PORTB = (1<<ROW1); */ // 6 - -
"L_red%=: \n\t" /* red: add RED_OFFSET (do nothing) */ "ldi r30, lo8(%2) \n\t" /* pCurrentStep = &rawdata[0]; */ // 7 - -
#if (TARGET_HW) "ldi r31, hi8(%2) \n\t" // 8 - -
"ldi r24, 2 \n\t" "rjmp L_end%= \n\t" // 10 - -
"out %5, r24 \n\t" "L_green%=: \n\t" /* green: */
#endif /* (TARGET_HW) */ "ldi r24, %7 \n\t" /* PORTB = (1<<ROW2); */ // - 7 -
"rjmp L_skip%= \n\t" "ldi r30, lo8(%3) \n\t" /* pCurrentStep = &rawdata[1]; */ // - 8 -
"L_green%=: \n\t" /* green: add GREEN_OFFSET */ "ldi r31, hi8(%3) \n\t" // - 9 -
#if (TARGET_HW) "L_end%=: \n\t"
"ldi r24, 1 \n\t" "out %5, r24 \n\t" /* set PORTB */ // 11 10 12
"out %5, r24 \n\t" :: "r" (nextColor),
#endif /* (TARGET_HW) */ "r" (pCurrentStep),
"ldi r24, %3 \n\t" "i" (&chan_rawdata[0]), /* RED */
"L_add%=: \n\t" "i" (&chan_rawdata[1]), /* GREEN */
"add r30, r24 \n\t" "i" (&chan_rawdata[2]), /* BLUE */
"ldi r24, 0 \n\t" "I" (_SFR_IO_ADDR(PORTB)),
"adc r31, r24 \n\t" "i" ((1<<ROW1)), /* RED */
"L_skip%=: \n\t" "i" ((1<<ROW2)), /* GREEN */
"movw %2, r30 \n\t" "i" ((1<<ROW3)) /* BLUE */
:
: "r" (nextColor),
"z" (data),
"r" (pCurrentStep),
"M" (GREEN_OFFSET),
"M" (BLUE_OFFSET),
"I" (_SFR_IO_ADDR(PORTB))
: "r24"
); );
asm volatile( asm volatile(
/* load table values */ /* load table values 1+1+1+1+1+1+1+1+1 = 8 */
"movw r30, %0 \n\t"
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
"out %1, r24 \n\t" /* PORTA = *pCurrentStep++; */ "out %1, r24 \n\t" /* PORTA = *pCurrentStep++; */
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
@ -171,27 +148,27 @@ void __attribute__ ((naked)) SIG_OVERFLOW0 (void)
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
"out %3, r24 \n\t" /* OCR0 = *pCurrentStep++; */ "out %3, r24 \n\t" /* OCR0 = *pCurrentStep++; */
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
"movw %4, r30 \n\t" "movw %0, r30 \n\t"
:: "r" (pCurrentStep),
"I" (_SFR_IO_ADDR(PORTA)),
"I" (_SFR_IO_ADDR(PORTC)),
"I" (_SFR_IO_ADDR(OCR0))
);
/* check if IRQ must be enabled */ asm volatile(
/* check if IRQ must be enabled 1+1+1+1+1+1+1 = 3/7 */
"or r24, r24 \n\t" /* if (*pCurrentStep++) { */ "or r24, r24 \n\t" /* if (*pCurrentStep++) { */
"breq L_skip%= \n\t" "breq L_skip%= \n\t"
"ldi r24, %5 \n\t" /* TIFR = (1<<OCF0); */ "ldi r24, %1 \n\t" /* TIFR = (1<<OCF0); */
"out %6, r24 \n\t" "out %0, r24 \n\t"
"in r24, %7 \n\t" /* TIMSK |= (1<<OCIE0); */ "in r24, %2 \n\t" /* TIMSK |= (1<<OCIE0); */
"ori r24, %8 \n\t" "ori r24, %3 \n\t"
"out %7, r24 \n\t" "out %2, r24 \n\t"
"L_skip%=: \n\t" /* } */ "L_skip%=: \n\t" /* } */
: "=r" (pCurrentStep) :: "I" (_SFR_IO_ADDR(TIFR)),
: "I" (_SFR_IO_ADDR(PORTA)), "M" ((1<<OCF0)),
"I" (_SFR_IO_ADDR(PORTC)), "I" (_SFR_IO_ADDR(TIMSK)),
"I" (_SFR_IO_ADDR(OCR0)), "M" ((1<<OCIE0))
"0" (pCurrentStep),
"M" ((1<<OCF0)),
"I" (_SFR_IO_ADDR(TIFR)),
"I" (_SFR_IO_ADDR(TIMSK)),
"M" ((1<<OCIE0))
: "r24", "r30", "r31"
); );
asm volatile( asm volatile(
@ -206,6 +183,7 @@ void __attribute__ ((naked)) SIG_OVERFLOW0 (void)
); );
} }
/* worst case: 9+9+5+13 = 36 clks -> 4.5us @ 8MHz */
void __attribute__ ((naked)) SIG_OUTPUT_COMPARE0 (void) void __attribute__ ((naked)) SIG_OUTPUT_COMPARE0 (void)
{ {
asm volatile( asm volatile(
@ -219,7 +197,7 @@ void __attribute__ ((naked)) SIG_OUTPUT_COMPARE0 (void)
); );
asm volatile( asm volatile(
/* load table values 1+2+1+2+1+2+1+2+1 = 13 */ /* load table values 1+1+1+1+1+1+1+1+1 = 9 */
"movw r30, %0 \n\t" "movw r30, %0 \n\t"
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
"out %1, r24 \n\t" /* PORTA = *pCurrentStep++; */ "out %1, r24 \n\t" /* PORTA = *pCurrentStep++; */
@ -228,23 +206,23 @@ void __attribute__ ((naked)) SIG_OUTPUT_COMPARE0 (void)
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
"out %3, r24 \n\t" /* OCR0 = *pCurrentStep++; */ "out %3, r24 \n\t" /* OCR0 = *pCurrentStep++; */
"ld r24, z+ \n\t" "ld r24, z+ \n\t"
"movw %4, r30 \n\t" "movw %0, r30 \n\t"
:: "r" (pCurrentStep),
"I" (_SFR_IO_ADDR(PORTA)),
"I" (_SFR_IO_ADDR(PORTC)),
"I" (_SFR_IO_ADDR(OCR0))
);
/* check if IRQ must be disabled 1+1+1+1+1 = 5 */ asm volatile(
"or r24, r24 \n\t" /* if (!(*pCurrentStep++)) */ /* check if IRQ must be disabled 1+1+1+1+1 = 3/5 */
"or r24, r24 \n\t" /* if (!(*pCurrentStep++)) { */
"brne L_skip%= \n\t" "brne L_skip%= \n\t"
"in r24, %5 \n\t" /* TIMSK &= ~(1<<OCIE0); */ "in r24, %0 \n\t" /* TIMSK &= ~(1<<OCIE0); */
"andi r24, %6 \n\t" "andi r24, %1 \n\t"
"out %5, r24 \n\t" "out %0, r24 \n\t"
"L_skip%=: \n\t" "L_skip%=: \n\t" /* } */
: "=r" (pCurrentStep) :: "I" (_SFR_IO_ADDR(TIMSK)),
: "I" (_SFR_IO_ADDR(PORTA)), "M" (0xFD) /* ~(1<<OCIE0) */
"I" (_SFR_IO_ADDR(PORTC)),
"I" (_SFR_IO_ADDR(OCR0)),
"0" (pCurrentStep),
"I" (_SFR_IO_ADDR(TIMSK)),
"M" (0xFD) /* ~(1<<OCIE0) */
: "r24", "r30", "r31"
); );
asm volatile( asm volatile(
@ -259,56 +237,6 @@ void __attribute__ ((naked)) SIG_OUTPUT_COMPARE0 (void)
); );
} }
#else /* !ASM_IRQS */
ISR(SIG_OVERFLOW0)
{
switch (nextColor++) {
case 0:
pCurrentStep = data + RED_OFFSET;
#if (TARGET_HW)
PORTB = 0x02;
#endif /* (TARGET_HW) */
break;
case 1:
pCurrentStep = data + GREEN_OFFSET;
#if (TARGET_HW)
PORTB = 0x01;
#endif /* (TARGET_HW) */
break;
default:
pCurrentStep = data + BLUE_OFFSET;
nextColor = 0;
#if (TARGET_HW)
PORTB = 0x08;
#endif /* (TARGET_HW) */
break;
}
PORTA = *pCurrentStep++;
PORTC = *pCurrentStep++;
OCR0 = *pCurrentStep++;
if (*pCurrentStep++) {
TIFR = (1<<OCF0);
TIMSK |= (1<<OCIE0);
}
}
ISR(SIG_OUTPUT_COMPARE0)
{
PORTA = *pCurrentStep++;
PORTC = *pCurrentStep++;
OCR0 = *pCurrentStep++;
if (!(*pCurrentStep++)) {
TIMSK &= ~(1<<OCIE0);
}
}
#endif /* ASM_IRQS */
static void calculate_timer_values(uint8_t *value, uint8_t *pDataStart) static void calculate_timer_values(uint8_t *value, uint8_t *pDataStart)
{ {
@ -383,7 +311,7 @@ static void calculate_timer_values(uint8_t *value, uint8_t *pDataStart)
*pData++ = ((chan_init >> 8) & 0xFF); /* PORTC */ *pData++ = ((chan_init >> 8) & 0xFF); /* PORTC */
} }
#if (!TARGET_HW) && (BAUDRATE) #if (BAUDRATE)
void print_values(uint8_t *data) void print_values(uint8_t *data)
{ {
uint8_t i; uint8_t i;
@ -397,7 +325,9 @@ void print_values(uint8_t *data)
break; break;
} }
} }
#endif /* (!TARGET_HW) && (BAUDRATE) */ #else
#define print_values(data)
#endif /* (BAUDRATE) */
int main(void) int main(void)
{ {
@ -405,29 +335,21 @@ int main(void)
PORTA = 0x00; PORTA = 0x00;
DDRA = 0xFF; DDRA = 0xFF;
#if (TARGET_HW)
PORTB = 0x00; PORTB = 0x00;
DDRB = (1<<ROW1) | (1<<ROW2) | (1<<ROW3) | (1<<ROW4); DDRB = (1<<ROW1) | (1<<ROW2) | (1<<ROW3) | (1<<ROW4);
#endif /* (TARGET_HW) */
PORTC = 0x00; PORTC = 0x00;
DDRC = 0xFF; DDRC = 0xFF;
#if (TARGET_HW)
PORTD = (1<<RXTX) | (1<<LED); PORTD = (1<<RXTX) | (1<<LED);
DDRD = (1<<RXTX) | (1<<LED); DDRD = (1<<RXTX) | (1<<LED);
#endif /* (TARGET_HW) */
/* timer0, FCPU/64, overflow interrupt */ /* timer0, FCPU/64, overflow interrupt */
#if (ASM_IRQS)
TCCR0 = (1<<CS01) | (1<<CS00); /* FCPU/64 */ TCCR0 = (1<<CS01) | (1<<CS00); /* FCPU/64 */
#else /* (!ASM_IRQS) */
TCCR0 = (1<<CS02); /* FCPU/256 */
#endif /* (ASM_IRQS) */
TIMSK = (1<<TOIE0); TIMSK = (1<<TOIE0);
TCNT0 = 0x00; TCNT0 = 0x00;
#if (!TARGET_HW) && (BAUDRATE) #if (BAUDRATE)
/* Set baud rate */ /* Set baud rate */
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF; UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
@ -437,45 +359,38 @@ int main(void)
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
fprintf(&uart, "good morning dave\n"); fprintf(&uart, "good morning dave\n");
#endif /* (!TARGET_HW) && (BAUDRATE) */ #endif /* (BAUDRATE) */
sei(); sei();
uint8_t x = 0; uint8_t x = 0;
uint8_t xdir = 1; uint8_t xdir = 1;
uint8_t ramp = 0; uint16_t ramp = 0;
uint8_t color[3] = { 0xFF, 0x00, 0x00 };
uint8_t step = 0; uint8_t step = 0;
while (1) { while (1) {
uint8_t color_update = 0x07; uint8_t color_update = 0x07;
while (color_update) { while (color_update) {
if ((color_update & 0x01) && (nextColor == 2)) { if ((color_update & 0x01) && (nextColor == 2)) {
calculate_timer_values(valueR, data + RED_OFFSET); calculate_timer_values(chan_value[0], chan_rawdata[0]);
color_update &= ~(0x01); color_update &= ~(0x01);
#if (!TARGET_HW) && (BAUDRATE) print_values(chan_rawdata[0]);
print_values(data + RED_OFFSET);
#endif /* (!TARGET_HW) && (BAUDRATE) */
} else if ((color_update & 0x02) && (nextColor == 0)) { } else if ((color_update & 0x02) && (nextColor == 0)) {
calculate_timer_values(valueG, data + GREEN_OFFSET); calculate_timer_values(chan_value[1], chan_rawdata[1]);
color_update &= ~(0x02); color_update &= ~(0x02);
#if (!TARGET_HW) && (BAUDRATE) print_values(chan_rawdata[1]);
print_values(data + GREEN_OFFSET);
#endif /* (!TARGET_HW) && (BAUDRATE) */
} else if ((color_update & 0x04) && (nextColor == 1)) { } else if ((color_update & 0x04) && (nextColor == 1)) {
calculate_timer_values(valueB, data + BLUE_OFFSET); calculate_timer_values(chan_value[2], chan_rawdata[2]);
color_update &= ~(0x04); color_update &= ~(0x04);
#if (!TARGET_HW) && (BAUDRATE) print_values(chan_rawdata[2]);
print_values(data + BLUE_OFFSET);
#endif /* (!TARGET_HW) && (BAUDRATE) */
} }
} }
#if (TARGET_HW)
PORTD ^= (1<<LED); PORTD ^= (1<<LED);
#endif /* (TARGET_HW) */
_delay_ms(100);
step++; step++;
if (step == 16) { if (step == 16) {
@ -497,77 +412,66 @@ int main(void)
} }
} }
switch (ramp) { uint8_t color[3];
ramp++;
switch (ramp >> 8) {
case 6:
ramp = 0x0000;
/* no break */
case 0: /* red: on, green: ramp up, blue: off */ case 0: /* red: on, green: ramp up, blue: off */
color[1]++; color[0] = 0xFF;
if (color[1] == 0xFF) color[1] = ramp & 0xFF;
ramp++; color[2] = 0x00;
break; break;
case 1: /* red: ramp down, green: on, blue:off */ case 1: /* red: ramp down, green: on, blue:off */
color[0]--; color[0] = 0xFF - (ramp & 0xFF);
if (color[0] == 0x00) color[1] = 0xFF;
ramp++; color[2] = 0x00;
break; break;
case 2: /* red: off, green: on, blue: ramp up */ case 2: /* red: off, green: on, blue: ramp up */
color[2]++; color[0] = 0x00;
if (color[2] == 0xFF) color[1] = 0xFF;
ramp++; color[2] = (ramp & 0xFF);
break; break;
case 3: /* red: off, green: ramp down: blue: on */ case 3: /* red: off, green: ramp down: blue: on */
color[1]--; color[0] = 0x00;
if (color[1] == 0x00) color[1] = 0xFF - (ramp & 0xFF);
ramp++; color[2] = 0xFF;
break; break;
case 4: /* red: ramp up, green: off, blue: on */ case 4: /* red: ramp up, green: off, blue: on */
color[0]++; color[0] = (ramp & 0xFF);
if (color[0] == 0xFF) color[1] = 0x00;
ramp++; color[2] = 0xFF;
break; break;
case 5: /* red: on, green: off, blue: ramp down */ case 5: /* red: on, green: off, blue: ramp down */
color[2]--; color[0] = 0xFF;
if (color[2] == 0x00) color[1] = 0x00;
ramp = 0; color[2] = 0xFF - (ramp & 0xFF);
break; break;
} }
uint8_t i; uint8_t i, j;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
for (j = 0; j < 3; j++) {
#if 0 #if 0
if (x == i) { if (x == i) {
valueR[i] = color[0]; chan_value[j][i] = color[j];
valueG[i] = color[1];
valueB[i] = color[2];
} else { } else if (chan_value[j][i] > 0) {
// valueR[i] = 0; uint8_t tmp = (chan_value[j][i] >> 5);
// valueG[i] = 0; chan_value[j][i] -= (tmp > 0) ? tmp : 1;
// valueB[i] = 0;
if (valueR[i] > 0) {
uint8_t tmp = (valueR[i] >> 5);
valueR[i] -= (tmp > 0) ? tmp : 1;
} }
if (valueG[i] > 0) {
uint8_t tmp = (valueG[i] >> 5);
valueG[i] -= (tmp > 0) ? tmp : 1;
}
if (valueB[i] > 0) {
uint8_t tmp = (valueB[i] >> 5);
valueB[i] -= (tmp > 0) ? tmp : 1;
}
}
#else #else
valueR[i] = color[0]; chan_value[j][i] = color[j];
valueG[i] = color[1];
valueB[i] = color[2];
#endif #endif
}
} }
} }