working 16ch RGB version

This commit is contained in:
Olaf Rempel 2011-11-14 20:23:01 +01:00
commit c9f2f64636
3 changed files with 294 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.o
*.elf
*.bin
*.hex
*.lst
*.map

52
Makefile Normal file
View File

@ -0,0 +1,52 @@
PRG = 16ch_pwm
OBJ = main.o
MCU_TARGET = atmega16
OPTIMIZE = -O2
DEFS =
LIBS =
# You should not have to change anything below here.
CC = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
override LDFLAGS = -Wl,-Map,$(PRG).map
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
all: $(PRG).elf lst text
$(SIZE) -x -A $(PRG).elf
$(PRG).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
rm -rf *.o *.lst *.map $(PRG).elf *.hex *.bin
lst: $(PRG).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
# Rules for building the .text rom images
text: hex bin
hex: $(PRG).hex
bin: $(PRG).bin
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@
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

236
main.c Normal file
View File

@ -0,0 +1,236 @@
/***************************************************************************
* C based avr910 / avr109 ISP Adapter *
* *
* Copyright (C) 2006 - 20011 by Olaf Rempel *
* razzor AT kopf MINUS tisch DOT de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License, *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
/*
* using ATmega16 @7.3728MHz:
* Fuse H: 0xDA (512 words bootloader, jtag disabled)
* Fuse L: 0xFF (ext. Crystal)
*/
#define F_CPU 7372800
#include <util/delay.h>
#define BAUDRATE 9600
#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);
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}
static FILE uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
#endif
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 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,
};
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,
};
static uint8_t *current_comp_reg;
static uint8_t comp_regR[16];
static uint8_t comp_regG[16];
static uint8_t comp_regB[16];
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];
static uint8_t current_color;
ISR(SIG_OVERFLOW0)
{
#if 0
/* switch color */
switch (current_color) {
case 0: /* RED */
current_comp_reg = comp_regR;
current_port_reg = port_regR;
current_color = 1;
break;
case 1: /* GREEN */
current_comp_reg = comp_regG;
current_port_reg = port_regG;
current_color = 2;
break;
case 2: /* BLUE */
current_comp_reg = comp_regB;
current_port_reg = port_regB;
current_color = 0;
break;
}
#else
current_comp_reg = comp_regR;
current_port_reg = port_regR;
#endif
uint16_t port_reg = *current_port_reg++;
PORTA = (port_reg & 0xFF);
PORTC = (port_reg >> 8) & 0xFF;
/* enable compare interrupts if any pin is active */
if (port_reg != 0x0000) {
TIMSK |= (1<<OCIE0);
}
OCR0 = *current_comp_reg++;
}
ISR(SIG_OUTPUT_COMPARE0)
{
uint16_t port_reg = *current_port_reg++;
PORTA = (port_reg & 0xFF);
PORTC = (port_reg >> 8) & 0xFF;
/* no further compare interrupts needed */
if (port_reg == 0x0000) {
TIMSK &= ~(1<<OCIE0);
}
OCR0 = *current_comp_reg++;
}
static void calculate_timer_values(uint8_t *value, uint8_t *comp_reg, uint16_t *port_reg)
{
uint8_t index = 0;
uint16_t chan_used = 0xFFFF;
uint16_t chan_init = 0xFFFF;
/* loop until all channels are calculated */
while (chan_used) {
uint8_t i;
uint8_t min_value = 0xFF;
uint16_t chan_tmp = chan_used;
uint16_t chan_mask = 0x0001;
for (i = 0; i < 16; i++) {
/* skip if channel already used */
if (chan_used & chan_mask)
{
/* channel is not used (value 0x00) */
if (value[i] == 0x00) {
chan_init &= (~chan_mask);
chan_used &= (~chan_mask);
/* found a new lower value */
} else if (value[i] < min_value) {
min_value = value[i];
chan_tmp = chan_used & (~chan_mask);
/* found another value with the same value */
} else if (value[i] == min_value) {
chan_tmp &= (~chan_mask);
}
}
chan_mask <<= 1;
}
chan_used &= chan_tmp;
// TODO: what if all channels are 0xFF, old value?
if (min_value < 0xFF) {
comp_reg[index] = min_value -1;
port_reg[index +1] = chan_used;
}
index++;
}
while (index < 16) {
comp_reg[index] = 0x00;
port_reg[index +1] = chan_used;
index++;
}
port_reg[0] = chan_init;
}
int main(void)
{
/* 16 PWM Outputs */
PORTA = 0x00;
PORTC = 0x00;
DDRA = 0xFF;
DDRC = 0xFF;
/* timer0, FCPU/256, overflow interrupt */
TCCR0 = (1<<CS02);
TIMSK = (1<<TOIE0);
TCNT0 = 0x00;
/* Set baud rate */
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
/* enable usart with 8n1 */
UCSRB = (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
// fprintf(&uart, "good morning dave\n");
PORTA = 0x01;
calculate_timer_values(valueR, comp_regR, port_regR);
PORTA = 0x02;
calculate_timer_values(valueG, comp_regG, port_regG);
PORTA = 0x04;
calculate_timer_values(valueB, comp_regB, port_regB);
PORTA = 0x00;
sei();
while (1);
return 0;
}