working 16ch RGB version
This commit is contained in:
commit
c9f2f64636
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.o
|
||||
*.elf
|
||||
*.bin
|
||||
*.hex
|
||||
*.lst
|
||||
*.map
|
52
Makefile
Normal file
52
Makefile
Normal 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
236
main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user