From 72226b24a9a987d8e8e32dc299677131b41aca15 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Sat, 7 Jan 2012 19:57:34 +0100 Subject: [PATCH] working --- Makefile | 5 +- main.c | 531 +++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 438 insertions(+), 98 deletions(-) diff --git a/Makefile b/Makefile index d74ea36..8fe4940 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PRG = 16ch_pwm OBJ = main.o -MCU_TARGET = atmega16 +MCU_TARGET = atmega32 OPTIMIZE = -O2 DEFS = @@ -49,4 +49,5 @@ bin: $(PRG).bin install: text # uisp -dprog=stk200 --erase --upload if=$(PRG).hex --verify # avrdude -p m16 -c butterfly -b 19200 -P /dev/ttyUSB0 -U flash:w:$(PRG).hex - avrdude -p m16 -c dragon_isp -P usb -U flash:w:$(PRG).hex +# avrdude -p m16 -c dragon_isp -P usb -U flash:w:$(PRG).hex + avrdude -p m32 -c dragon_isp -P usb -U flash:w:$(PRG).hex diff --git a/main.c b/main.c index 725544b..000bf4d 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /*************************************************************************** - * C based avr910 / avr109 ISP Adapter * + * 16ch RGB 8bit PWM controller * * * * Copyright (C) 2006 - 20011 by Olaf Rempel * * razzor AT kopf MINUS tisch DOT de * @@ -24,22 +24,51 @@ #include /* - * using ATmega16 @7.3728MHz: - * Fuse H: 0xDA (512 words bootloader, jtag disabled) - * Fuse L: 0xFF (ext. Crystal) + * using ATmega32 @8MHz: + * Fuse H: 0xD9 (no bootloader, jtag disabled) + * Fuse L: 0xD4 (int. 8MHz Osz, fast rising power, no BOD) + * + * PA0..7 -> COL1..8 + * PC0..7 -> COL9..16 + * PB0 / PD7(OC2) -> ROW4 + * PB1 / PD5(OC1A) -> ROW3 + * PB2 / PD4(OC1B) -> ROW2 + * PB3(OC0) / PD6 -> ROW1 + * PD0 -> RXD + * PD1 -> TXD + * PD2 -> /RX_TX + * PD3 -> /LED */ +#define TARGET_HW 1 +#define ASM_IRQS 1 + +#if (TARGET_HW) +#define F_CPU 8000000 +#else +#define F_CPU 7372800 +#endif -#define F_CPU 7372800 #include -#define BAUDRATE 9600 +#define ROW1 PORTB3 +#define ROW2 PORTB2 +#define ROW3 PORTB1 +#define ROW4 PORTB0 + +#define RXTX PORTD2 +#define LED PORTD3 + +//#define BAUDRATE 115200 + +#if (!TARGET_HW) && (BAUDRATE) #define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1) -#if 0 static int uart_putchar(char c, FILE *stream) { - if (c == '\n') - uart_putchar('\r', stream); + if (c == '\n') { + loop_until_bit_is_set(UCSRA, UDRE); + UDR = '\r'; + } loop_until_bit_is_set(UCSRA, UDRE); UDR = c; @@ -47,97 +76,243 @@ static int uart_putchar(char c, FILE *stream) } static FILE uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); -#endif +#endif /* (!TARGET_HW) && (BAUDRATE) */ -static uint8_t valueR[16] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -// 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, -// 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, -}; +static uint8_t valueR[16]; +static uint8_t valueG[16]; +static uint8_t valueB[16]; -static uint8_t valueG[16] = { - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -// 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, -// 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, -}; +/* keep color in r4 */ +register uint8_t nextColor asm("r4"); -static uint8_t valueB[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -// 0xF1, 0xF3, 0xF5, 0xF7, 0xF9, 0xFB, 0xFD, 0xFF, -// 0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE, -}; +/* keep pointer in r2:r3 */ +register uint8_t * pCurrentStep asm("r2"); -static uint8_t *current_comp_reg; -static uint8_t comp_regR[16]; -static uint8_t comp_regG[16]; -static uint8_t comp_regB[16]; +/* 16 +1 * 4 values (portA, portC, OCR0, flags) per color */ +static uint8_t data[17 * 4 * 3]; -static uint16_t *current_port_reg; -static uint16_t port_regR[16 +1]; -static uint16_t port_regG[16 +1]; -static uint16_t port_regB[16 +1]; +/* offsets in data array */ +#define RED_OFFSET (17 * 4 * 0) +#define GREEN_OFFSET (17 * 4 * 1) +#define BLUE_OFFSET (17 * 4 * 2) -static uint8_t current_color; + +#if ASM_IRQS +void __attribute__ ((naked)) SIG_OVERFLOW0 (void) +{ + asm volatile( + /* save registers 2+1+2+2+2 = 9 */ + "push r24 \n\t" + "in r24, __SREG__ \n\t" + "push r24 \n\t" + "push r30 \n\t" + "push r31 \n\t" + :: + ); + + asm volatile( + "clr r24 \n\t" + "out %0, r24 \n\t" /* PORTA = 0x00; */ + "out %1, r24 \n\t" /* PORTC = 0x00; */ + : + : "I" (_SFR_IO_ADDR(PORTA)), + "I" (_SFR_IO_ADDR(PORTC)) + ); + + asm volatile( + /* switch color, assign pCurrentStep = data + RED/GREEN/BLUE_OFFSET */ + "mov r24, %0 \n\t" + "inc %0 \n\t" /* nextColor++ */ + "cpi r24, 1 \n\t" + "brlo L_red%= \n\t" /* if (nextColor < 1) -> red */ + "breq L_green%= \n\t" /* if (nextColor == 1) -> green */ + "clr %0 \n\t" /* else set nextColor = 0, add BLUE_OFFSET */ +#if (TARGET_HW) + "ldi r24, 8 \n\t" + "out %5, r24 \n\t" +#endif /* (TARGET_HW) */ + "ldi r24, %4 \n\t" + "rjmp L_add%= \n\t" + "L_red%=: \n\t" /* red: add RED_OFFSET (do nothing) */ +#if (TARGET_HW) + "ldi r24, 2 \n\t" + "out %5, r24 \n\t" +#endif /* (TARGET_HW) */ + "rjmp L_skip%= \n\t" + "L_green%=: \n\t" /* green: add GREEN_OFFSET */ +#if (TARGET_HW) + "ldi r24, 1 \n\t" + "out %5, r24 \n\t" +#endif /* (TARGET_HW) */ + "ldi r24, %3 \n\t" + "L_add%=: \n\t" + "add r30, r24 \n\t" + "ldi r24, 0 \n\t" + "adc r31, r24 \n\t" + "L_skip%=: \n\t" + "movw %2, r30 \n\t" + : + : "r" (nextColor), + "z" (data), + "r" (pCurrentStep), + "M" (GREEN_OFFSET), + "M" (BLUE_OFFSET), + "I" (_SFR_IO_ADDR(PORTB)) + : "r24" + ); + + asm volatile( + /* load table values */ + "movw r30, %0 \n\t" + "ld r24, z+ \n\t" + "out %1, r24 \n\t" /* PORTA = *pCurrentStep++; */ + "ld r24, z+ \n\t" + "out %2, r24 \n\t" /* PORTC = *pCurrentStep++; */ + "ld r24, z+ \n\t" + "out %3, r24 \n\t" /* OCR0 = *pCurrentStep++; */ + "ld r24, z+ \n\t" + "movw %4, r30 \n\t" + + /* check if IRQ must be enabled */ + "or r24, r24 \n\t" /* if (*pCurrentStep++) { */ + "breq L_skip%= \n\t" + "ldi r24, %5 \n\t" /* TIFR = (1<> 8) & 0xFF; + PORTA = *pCurrentStep++; + PORTC = *pCurrentStep++; + OCR0 = *pCurrentStep++; - /* enable compare interrupts if any pin is active */ - if (port_reg != 0x0000) { + if (*pCurrentStep++) { + TIFR = (1<> 8) & 0xFF; + PORTA = *pCurrentStep++; + PORTC = *pCurrentStep++; + OCR0 = *pCurrentStep++; - /* no further compare interrupts needed */ - if (port_reg == 0x0000) { + if (!(*pCurrentStep++)) { TIMSK &= ~(1<> 8) & 0xFF); /* PORTC */ + + /* previous step needs timervalue and enable IRQ */ + *(pData++ -4) = min_value -0; /* OCR0 */ /* FIXME: -1 ? */ + *(pData++ -4) = 0x01; /* flags */ } index++; } + /* fill all remaining slots */ while (index < 16) { - comp_reg[index] = 0x00; - port_reg[index +1] = chan_used; + /* repeat enabled outputs */ + *pData++ = (chan_used & 0xFF); /* PORTA */ + *pData++ = ((chan_used >> 8) & 0xFF); /* PORTC */ + + /* previous step was last one (no timevalue / disable IRQ) */ + *(pData++ -4) = 0x00; /* OCR0 */ + *(pData++ -4) = 0x00; /* flags */ + index++; } - port_reg[0] = chan_init; + /* first slot/init: enable only channels that are > 0 */ + pData = pDataStart; + *pData++ = (chan_init & 0xFF); /* PORTA */ + *pData++ = ((chan_init >> 8) & 0xFF); /* PORTC */ } +#if (!TARGET_HW) && (BAUDRATE) +void print_values(uint8_t *data) +{ + uint8_t i; + + for (i = 0; i < 17; i++) { + fprintf(&uart, "%2d: %02X %02X %02X %02X\n", i, + data[(i<<2)], data[(i<<2) +1], + data[(i<<2) +2], data[(i<<2) +3]); + + if (data[(i<<2) +3] == 0x00) + break; + } +} +#endif /* (!TARGET_HW) && (BAUDRATE) */ int main(void) { /* 16 PWM Outputs */ PORTA = 0x00; - PORTC = 0x00; - DDRA = 0xFF; - DDRC = 0xFF; + DDRA = 0xFF; - /* timer0, FCPU/256, overflow interrupt */ - TCCR0 = (1<>8) & 0xFF; UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); @@ -216,21 +436,140 @@ int main(void) UCSRB = (1< 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 + valueR[i] = color[0]; + valueG[i] = color[1]; + valueB[i] = color[2]; +#endif + } + } return 0; }