Browse Source

initial dump to git

master
Jan Koppe 3 years ago
commit
6642c827dc
Signed by: j GPG Key ID: BE935B0735A2129B
  1. 20
      README.md
  2. 259
      lampe_control_avr/fw/Makefile
  3. 125
      lampe_control_avr/fw/\
  4. 66
      lampe_control_avr/fw/encoder.c
  5. 22
      lampe_control_avr/fw/encoder.h
  6. 182
      lampe_control_avr/fw/light_ws2812.c
  7. 75
      lampe_control_avr/fw/light_ws2812.h
  8. 175
      lampe_control_avr/fw/main.c
  9. 19
      lampe_control_avr/fw/main.h
  10. 777
      lampe_control_avr/fw/uart.c
  11. 207
      lampe_control_avr/fw/uart.h
  12. 34
      lampe_control_avr/fw/ws2812_config.h
  13. 9
      lampe_control_avr/irfl014n.dcm
  14. 38
      lampe_control_avr/irfl014n.lib
  15. 2359
      lampe_control_avr/lampe_control_avr-B.Cu.gbr
  16. 95
      lampe_control_avr/lampe_control_avr-B.Mask.gbr
  17. 12
      lampe_control_avr/lampe_control_avr-B.Paste.gbr
  18. 174
      lampe_control_avr/lampe_control_avr-B.SilkS.gbr
  19. 24
      lampe_control_avr/lampe_control_avr-Edge.Cuts.gbr
  20. 3350
      lampe_control_avr/lampe_control_avr-F.Cu.gbr
  21. 169
      lampe_control_avr/lampe_control_avr-F.Mask.gbr
  22. 86
      lampe_control_avr/lampe_control_avr-F.Paste.gbr
  23. 7082
      lampe_control_avr/lampe_control_avr-F.SilkS.gbr
  24. 379
      lampe_control_avr/lampe_control_avr-cache.lib
  25. 717
      lampe_control_avr/lampe_control_avr.bak
  26. 85
      lampe_control_avr/lampe_control_avr.drl
  27. 2811
      lampe_control_avr/lampe_control_avr.kicad_pcb
  28. 2801
      lampe_control_avr/lampe_control_avr.kicad_pcb-bak
  29. 494
      lampe_control_avr/lampe_control_avr.net
  30. 74
      lampe_control_avr/lampe_control_avr.pro
  31. 717
      lampe_control_avr/lampe_control_avr.sch
  32. 175
      lampe_leds/lampe_eds.lib
  33. 9392
      lampe_leds/lampe_leds-B.Cu.gbr
  34. 163
      lampe_leds/lampe_leds-B.Mask.gbr
  35. 134
      lampe_leds/lampe_leds-B.Paste.gbr
  36. 8978
      lampe_leds/lampe_leds-B.SilkS.gbr
  37. 22
      lampe_leds/lampe_leds-Edge.Cuts.gbr
  38. 15670
      lampe_leds/lampe_leds-F.Cu.gbr
  39. 532
      lampe_leds/lampe_leds-F.Mask.gbr
  40. 263
      lampe_leds/lampe_leds-F.Paste.gbr
  41. 3938
      lampe_leds/lampe_leds-F.SilkS.gbr
  42. 168
      lampe_leds/lampe_leds.drl
  43. 11028
      lampe_leds/lampe_leds.kicad_pcb
  44. 11028
      lampe_leds/lampe_leds.kicad_pcb-bak
  45. 1305
      lampe_leds/lampe_leds.net
  46. 66
      lampe_leds/lampe_leds.pro
  47. 3950
      lampe_leds/lampe_leds.sch

20
README.md

@ -0,0 +1,20 @@
# Lampe
This is a little workbench-light using sixty SK6812 WWA LEDs. With a beefy 5V/4A power supply you can make a lot of light with controllable color temperature. Control input can come from the on-board rotary encoder or via serial commands. The board includes a temperature Sensor with PTC + adc on the µC and a mosfet-driven fan output with PWM control
This is a work in progress.
Finished:
* LED PCB. This is working really well.
Things that need to be done still:
* Include a serial port on the control PCB, ideally with an USB bridge, or maybe just V-USB on the µC itself?
* Read out the PTC with ADC as a temperature sensor. Maybeswitch to an I²C sensor?
* Couple temperature to fan control
* Figure out what to do with the optional I²C SSD1306 OLED display.
The first AVR control PCB batch has a bunch of bugs, so if I gave you a PCB at GPN18 or sometime else:
* You will need to bodge-wire the data-in to some unused GPIO pin on the AVR.
* You can just bridge the AMS1117-3.3 voltage regulator pins - the µC runs just fine on 5V, and 16mhz/3.3v operation isn't officially supported anyway.

259
lampe_control_avr/fw/Makefile

@ -0,0 +1,259 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# AVR-GCC Makefile template, derived from the WinAVR template (public domain)
#
# --------------------------------- WARNING ---------------------------------
# Running "make fuses" can and will brick your AVR if you are not careful
# To avoid this I recommend consulting http://www.engbedded.com/fusecalc
#
# ---------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make fuses = Burn the fuses using avrdude.
# Please customize the avrdude fuse settings below first!
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
# ---------------------------------------------------------------------------
MCU = atmega8
FORMAT = ihex
TARGET = main
SRC = $(TARGET).c uart.c encoder.c light_ws2812.c
ASRC =
OPT = s
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS =
# Place -I options here
CINCS =
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes -Wundef
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums\
-ffunction-sections -ffreestanding -fwhole-program\
-fno-inline-small-functions -fno-split-wide-types -fno-tree-scev-cprop
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
#Additional libraries.
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
PRINTF_LIB =
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
SCANF_LIB =
MATH_LIB = -lm
# External memory options
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#LDMAP = $(LDFLAGS) -Wl,-Map=$(TARGET).map,--cref
LDFLAGS = $(EXTMEMOPTS) $(LDMAP) $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = buspirate
AVRDUDE_PORT = /dev/ttyUSB0
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
AVRDUDE_WRITE_FUSES = -U lfuse:w:ff:m -U hfuse:w:c9:m -U efuse:w:ff:m
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_BASIC = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) -P $(AVRDUDE_PORT)
AVRDUDE_FLAGS = $(AVRDUDE_BASIC) $(AVRDUDE_NO_VERIFY) $(AVRDUDE_VERBOSE) $(AVRDUDE_ERASE_COUNTER)
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: elf hex eep
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# Burn the fuses.
fuses:
$(AVRDUDE) $(AVRDUDE_BASIC) $(AVRDUDE_WRITE_FUSES)
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) #$(AVRDUDE_WRITE_EEPROM)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
$(COFFCONVERT) -O coff-avr $(TARGET).elf $(TARGET).cof
extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $(TARGET).elf $(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Link: create ELF output file from object files.
$(TARGET).elf: $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Target: clean project.
clean:
$(REMOVE) $(TARGET).hex $(TARGET).eep $(TARGET).cof $(TARGET).elf \
$(TARGET).map $(TARGET).sym $(TARGET).lss \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d)
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend

125
lampe_control_avr/fw/\

@ -0,0 +1,125 @@
#include "main.h"
struct cRGB led[LED_COUNT];
void adc_init (void) {
// enable internal vref
ADMUX |= (1 << REFS1) | (1 << REFS0);
// enable adc in free running mode with /64 prescaler, fixed adc0 input
ADCSRA |= (1 << ADEN) | (1 << ADFR) | (1 << ADPS2) | (1 << ADPS1);
}
void fan_init (void) {
// Set PB1/OC1A to output
DDRB |= (1 << 1);
// Set on match, clear on TOP
TCCR1A = ((1 << COM1A1) | (1 << COM1A0));
TCCR1B = ((1 << CS11) | (1 << CS10) | (1 << WGM13));
ICR1 = 2048;
}
void fan_set (unsigned int i) {
// sunon fan reliably starts up at ~768
i %= 255;
if (i >= 1) {
OCR1A = 1024 - (i * 4);
} else {
OCR1A = 2048;
}
}
void led_output(unsigned int brightness, unsigned int temperature, unsigned char en) {
unsigned int amber,warm,cold;
// translate temperature to color mixing
amber = ranged(1023 - x * 2, 1023)
cold = ranged(x * 2 - 1023, 1023)
if (x > 512) {
warm = 2047 - x * 2
} else {
warm = x * 2
}
// apply brightness
amber = (amber * brightness) / 255
if (en == 0) {
amber = 0;
warm = 0;
cold = 0;
}
for (int i = 0; i < LED_COUNT; i++) {
led[i].r = amber;
led[i].g = cold; // remap color order to actual leds
led[i].b = warm;
}
}
int ranged (int i, int max) {
if (i >= max) return max;
if (i <= 0) return 0;
return i;
}
int main (void) {
fan_init();
fan_set(0);
encoder_init();
uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
// vars for serial decode state machine
unsigned int c;
int ser_step = 0;
int temperature = 0;
char brightness = 0;
unsigned char enabled = 1;
// state vars if encoder was turned or depressed since last run
int diff = 0;
char btn = 0;
while (1) {
diff = encoder_read();
btn = encoder_read_btn();
if (diff != 0) {
// encoder was turned
if (btn == 1) {
temperature = ranged(temperature + (diff*7), 240);
} else {
brightness = ranged(brightness + (diff*2), 100);
}
}
// read serial port values
c = uart_getc();
if (!( c & UART_NO_DATA || c & UART_FRAME_ERROR || c & UART_OVERRUN_ERROR || c & UART_BUFFER_OVERFLOW)) {
if (c == 0xFF) {
ser_step = 0;
} else {
switch (ser_step++) {
case 0:
brightness = ranged(c, 100);
break;
case 1:
temperature = ranged(c, 240);
break;
}
}
}
// output new values
led_output(temperature, brightness, enabled);
ws2812_setleds (led, LED_COUNT);
// echo current settings over serial port
uart_putc(0xFF);
uart_putc(brightness);
uart_putc(temperature);
}
}

66
lampe_control_avr/fw/encoder.c

@ -0,0 +1,66 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include "encoder.h"
/*
* Code based on version from Peter Dannegger, see
* https://www.mikrocontroller.net/articles/Drehgeber#Signalauswertung
*/
volatile int delta = 0;
static int last;
static int btn;
void encoder_init( void )
{
int new;
// enable internal pull-up resistors
ENC_PORT |= (1 << ENC_PIN_A) | (1 << ENC_PIN_B);
ENC_PORT_BTN |= (1 << ENC_PIN_BTN);
new = 0;
if( INPUT_B ) new = 3;
if( INPUT_A ) new ^= 1;
last = new;
TCCR2 = (1 << WGM21) | (1 << WGM20) | (1<<CS22);
// setup compare register to trigger after 1ms
// OCR2 = (uint)(F_CPU / 64.0 * 1e-3 - 0.5);
// enable timer compare interrupt
TIMSK |= 1<<OCIE2;
}
ISR( TIMER2_COMP_vect ) // 1ms for manual movement
{
int new, diff;
new = 0;
if( INPUT_B ) new = 3;
if( INPUT_A ) new ^= 1; // convert gray to binary
diff = last - new; // difference last - new
if( diff & 1 ) { // bit 0 = value (1)
last = new; // store new as next last
delta += (diff & 2) - 1; // bit 1 = direction (+/-)
}
// button pressed is signal low, need to invert
btn = INPUT_BTN ^ 1;
}
int encoder_read( void ) // read four step encoders
{
int val;
cli();
val = delta;
delta = val & 3;
sei();
return val >> 2; // counts since last call
}
int encoder_read_btn( void ) // read button state
{
return btn;
}

22
lampe_control_avr/fw/encoder.h

@ -0,0 +1,22 @@
#ifndef ENCODER_H_
#define ENCODER_H_
#ifndef F_CPU
#define F_CPU 16000000
#endif
#define ENC_PORT PORTC
#define ENC_PORT_BTN PORTD
#define ENC_PIN_A PC1
#define ENC_PIN_B PC2
#define ENC_PIN_BTN PD2
#define INPUT_A (PINC & 1<<ENC_PIN_A)
#define INPUT_B (PINC & 1<<ENC_PIN_B)
#define INPUT_BTN (PIND & 1<<ENC_PIN_BTN)
void encoder_init( void );
int encoder_read( void );
int encoder_read_btn( void );
#endif

182
lampe_control_avr/fw/light_ws2812.c

@ -0,0 +1,182 @@
/*
* light weight WS2812 lib V2.0b
*
* Controls WS2811/WS2812/WS2812B RGB-LEDs
* Author: Tim (cpldcpu@gmail.com)
*
* Jan 18th, 2014 v2.0b Initial Version
* Nov 29th, 2015 v2.3 Added SK6812RGBW support
*
* License: GNU GPL v2+ (see License.txt)
*/
#include "light_ws2812.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
// Setleds for standard RGB
inline void ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
{
ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
}
inline void ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
{
ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask);
_delay_us(ws2812_resettime);
}
// Setleds for SK6812RGBW
inline void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds)
{
ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(ws2812_pin));
_delay_us(ws2812_resettime);
}
void ws2812_sendarray(uint8_t *data,uint16_t datlen)
{
ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin));
}
/*
This routine writes an array of bytes with RGB values to the Dataout pin
using the fast 800kHz clockless WS2811/2812 protocol.
*/
// Timing in ns
#define w_zeropulse 350
#define w_onepulse 900
#define w_totalperiod 1250
// Fixed cycles used by the inner loop
#define w_fixedlow 2
#define w_fixedhigh 4
#define w_fixedtotal 8
// Insert NOPs to match the timing, if possible
#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000)
#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000)
#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000)
// w1 - nops between rising edge and falling edge - low
#define w1 (w_zerocycles-w_fixedlow)
// w2 nops between fe low and fe high
#define w2 (w_onecycles-w_fixedhigh-w1)
// w3 nops to complete loop
#define w3 (w_totalcycles-w_fixedtotal-w1-w2)
#if w1>0
#define w1_nops w1
#else
#define w1_nops 0
#endif
// The only critical timing parameter is the minimum pulse length of the "0"
// Warn or throw error if this timing can not be met with current F_CPU settings.
#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
#if w_lowtime>550
#error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
#elif w_lowtime>450
#warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
#warning "Please consider a higher clockspeed, if possible"
#endif
#if w2>0
#define w2_nops w2
#else
#define w2_nops 0
#endif
#if w3>0
#define w3_nops w3
#else
#define w3_nops 0
#endif
#define w_nop1 "nop \n\t"
#define w_nop2 "rjmp .+0 \n\t"
#define w_nop4 w_nop2 w_nop2
#define w_nop8 w_nop4 w_nop4
#define w_nop16 w_nop8 w_nop8
inline void ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
{
uint8_t curbyte,ctr,masklo;
uint8_t sreg_prev;
ws2812_DDRREG |= maskhi; // Enable output
masklo =~maskhi&ws2812_PORTREG;
maskhi |= ws2812_PORTREG;
sreg_prev=SREG;
cli();
while (datlen--) {
curbyte=*data++;
asm volatile(
" ldi %0,8 \n\t"
"loop%=: \n\t"
" out %2,%3 \n\t" // '1' [01] '0' [01] - re
#if (w1_nops&1)
w_nop1
#endif
#if (w1_nops&2)
w_nop2
#endif
#if (w1_nops&4)
w_nop4
#endif
#if (w1_nops&8)
w_nop8
#endif
#if (w1_nops&16)
w_nop16
#endif
" sbrs %1,7 \n\t" // '1' [03] '0' [02]
" out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
" lsl %1 \n\t" // '1' [04] '0' [04]
#if (w2_nops&1)
w_nop1
#endif
#if (w2_nops&2)
w_nop2
#endif
#if (w2_nops&4)
w_nop4
#endif
#if (w2_nops&8)
w_nop8
#endif
#if (w2_nops&16)
w_nop16
#endif
" out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
#if (w3_nops&1)
w_nop1
#endif
#if (w3_nops&2)
w_nop2
#endif
#if (w3_nops&4)
w_nop4
#endif
#if (w3_nops&8)
w_nop8
#endif
#if (w3_nops&16)
w_nop16
#endif
" dec %0 \n\t" // '1' [+2] '0' [+2]
" brne loop%=\n\t" // '1' [+3] '0' [+4]
: "=&d" (ctr)
: "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo)
);
}
SREG=sreg_prev;
}

75
lampe_control_avr/fw/light_ws2812.h

@ -0,0 +1,75 @@
/*
* light weight WS2812 lib include
*
* Version 2.3 - Nev 29th 2015
* Author: Tim (cpldcpu@gmail.com)
*
* Please do not change this file! All configuration is handled in "ws2812_config.h"
*
* License: GNU GPL v2+ (see License.txt)
+
*/
#ifndef LIGHT_WS2812_H_
#define LIGHT_WS2812_H_
#include <avr/io.h>
#include <avr/interrupt.h>
#include "ws2812_config.h"
#ifndef F_CPU
#define F_CPU 16000000
#endif
/*
* Structure of the LED array
*
* cRGB: RGB for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106
* cRGBW: RGBW for SK6812RGBW
*/
struct cRGB { uint8_t g; uint8_t r; uint8_t b; };
struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;};
/* User Interface
*
* Input:
* ledarray: An array of GRB data describing the LED colors
* number_of_leds: The number of LEDs to write
* pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
*
* The functions will perform the following actions:
* - Set the data-out pin as output
* - Send out the LED data
* - Wait 50µs to reset the LEDs
*/
void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds);
void ws2812_setleds_pin (struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask);
void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds);
/*
* Old interface / Internal functions
*
* The functions take a byte-array and send to the data output as WS2812 bitstream.
* The length is the number of bytes to send - three per LED.
*/
void ws2812_sendarray (uint8_t *array,uint16_t length);
void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask);
/*
* Internal defines
*/
#define CONCAT(a, b) a ## b
#define CONCAT_EXP(a, b) CONCAT(a, b)
#define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port)
#define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port)
#endif /* LIGHT_WS2812_H_ */

175
lampe_control_avr/fw/main.c

@ -0,0 +1,175 @@
#include "main.h"
struct cRGB led[LED_COUNT];
void adc_init (void) {
// enable internal vref
ADMUX |= (1 << REFS1) | (1 << REFS0);
// enable adc in free running mode with /64 prescaler, fixed adc0 input
ADCSRA |= (1 << ADEN) | (1 << ADFR) | (1 << ADPS2) | (1 << ADPS1);
}
void fan_init (void) {
// Set PB1/OC1A to output
DDRB |= (1 << 1);
// Set on match, clear on TOP
TCCR1A = ((1 << COM1A1) | (1 << COM1A0));
TCCR1B = ((1 << CS11) | (1 << CS10) | (1 << WGM13));
ICR1 = 2048;
}
void fan_set (unsigned int i) {
// sunon fan reliably starts up at ~768
i %= 255;
if (i >= 1) {
OCR1A = 1024 - (i * 4);
} else {
OCR1A = 2048;
}
}
//############################################################################
//HSV to RGB 8Bit
//Farbkreis h = 0 bis 360 (Farbwert)
// s = 0 bis 100 (Dunkelstufe)
// v = 0 bis 100 (Farbsättigung)
//Rückgabewert r,g,b als Pointer
void hsv_to_rgb (unsigned int h,unsigned char s,unsigned char v,
unsigned char* r, unsigned char* g, unsigned char* b)
{
unsigned char diff;
//Winkel im Farbkeis 0 - 360 in 1 Grad Schritten
//h = (englisch hue) Farbwert
//1 Grad Schrittweite, 4.25 Steigung pro Schritt bei 60 Grad
if(h<61){
*r = 255;
*b = 0;
*g = (425 * h) / 100;
}else if(h < 121){
*g = 255;
*b = 0;
*r = 255 - ((425 * (h-60))/100);
}else if(h < 181){
*r = 0;
*g = 255;
*b = (425 * (h-120))/100;
}else if(h < 241){
*r = 0;
*b = 255;
*g = 255 - ((425 * (h-180))/100);
}else if(h < 301){
*g = 0;
*b = 255;
*r = (425 * (h-240))/100;
}else if(h< 360){
*r = 255;
*g = 0;
*b = 255 - ((425 * (h-300))/100);
}
//Berechnung der Farbsättigung
//s = (englisch saturation) Farbsättigung
s = 100 - s; //Kehrwert berechnen
diff = ((255 - *r) * s)/100;
*r = *r + diff;
diff = ((255 - *g) * s)/100;
*g = *g + diff;
diff = ((255 - *b) * s)/100;
*b = *b + diff;
//Berechnung der Dunkelstufe
//v = (englisch value) Wert Dunkelstufe einfacher Dreisatz 0..100%
*r = (*r * v)/100;
*g = (*g * v)/100;
*b = (*b * v)/100;
}
void led_fill (unsigned int h, unsigned int v, unsigned char en) {
// work as hsv model, hue = color temperature, value = brightness
// saturation = 1 for now
unsigned char amber,warm,cold;
hsv_to_rgb (h, 100, (unsigned char)v, &amber, &warm, &cold);
if (en == 0) {
amber = 0;
warm = 0;
cold = 0;
}
for (int i = 0; i < LED_COUNT; i++) {
led[i].r = amber;
led[i].g = cold; // remap color order to actual leds
led[i].b = warm;
}
}
int ranged (int i, int max) {
if (i >= max) return max;
if (i <= 0) return 0;
return i;
}
int main (void) {
fan_init();
fan_set(0);
encoder_init();
uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
// vars for serial decode state machine
unsigned int c;
int ser_step = 0;
int temperature = 0;
char brightness = 0;
unsigned char enabled = 1;
// state vars if encoder was turned or depressed since last run
int diff = 0;
char btn = 0;
while (1) {
diff = encoder_read();
btn = encoder_read_btn();
if (diff != 0) {
// encoder was turned
if (btn == 1) {
temperature = ranged(temperature + (diff*7), 240);
} else {
brightness = ranged(brightness + (diff*2), 100);
}
}
// read serial port values
c = uart_getc();
if (!( c & UART_NO_DATA || c & UART_FRAME_ERROR || c & UART_OVERRUN_ERROR || c & UART_BUFFER_OVERFLOW)) {
if (c == 0xFF) {
ser_step = 0;
} else {
switch (ser_step++) {
case 0:
brightness = ranged(c, 100);
break;
case 1:
temperature = ranged(c, 240);
break;
}
}
}
// output new values
led_fill(temperature, brightness, enabled);
ws2812_setleds (led, LED_COUNT);
// echo current settings over serial port
uart_putc(0xFF);
uart_putc(0xFF);
uart_putc(brightness);
uart_putc(temperature);
}
}

19
lampe_control_avr/fw/main.h

@ -0,0 +1,19 @@
#ifndef MAIN_H_
#define MAIN_H_
#ifndef F_CPU
#define F_CPU 16000000
#endif
#include <util/delay.h>
#include <stdlib.h>
#include "uart.h"
#include "encoder.h"
#include "light_ws2812.h"
#define LED_COUNT 60
#define UART_BAUD_RATE 9600
#define SER_BRIGHTNESS 0b10000000
#endif

777
lampe_control_avr/fw/uart.c

@ -0,0 +1,777 @@
/*************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury
File: $Id: uart.c,v 1.15.2.4 2015/09/05 18:33:32 peter Exp $
Software: AVR-GCC 4.x
Hardware: any AVR with built-in UART,
License: GNU General Public License
DESCRIPTION:
An interrupt is generated when the UART has finished transmitting or
receiving a byte. The interrupt handling routines use circular buffers
for buffering received and transmitted data.
The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
the buffer size in bytes. Note that these variables must be a
power of 2.
USAGE:
Refere to the header file uart.h for a description of the routines.
See also example test_uart.c.
NOTES:
Based on Atmel Application Note AVR306
LICENSE:
Copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
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; either version 2 of the License, or
any later version.
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.
*************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "uart.h"
/*
* constants and macros
*/
/* size of RX/TX buffers */
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif
#if defined(__AVR_AT90S2313__) || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || \
defined(__AVR_AT90S4434__) || defined(__AVR_AT90S8535__) || \
defined(__AVR_ATmega103__)
/* old AVR classic or ATmega103 with one UART */
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS USR
#define UART0_CONTROL UCR
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRR
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
/* old AVR classic with one UART */
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRR
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#elif defined(__AVR_AT90PWM216__) || defined(__AVR_AT90PWM316__)
/* AT90PWN216/316 with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega8A__) || \
defined(__AVR_ATmega16__) || defined(__AVR_ATmega16A__) || \
defined(__AVR_ATmega32__) || defined(__AVR_ATmega32A__) || \
defined(__AVR_ATmega323__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#define UART0_BIT_URSEL URSEL
#elif defined (__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#define UART0_BIT_URSEL URSEL
#elif defined(__AVR_ATmega163__)
/* ATmega163 with one UART */
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRR
#define UART0_UBRRH UBRRHI
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#elif defined(__AVR_ATmega162__)
/* ATmega with two USART */
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RXC_vect
#define UART1_RECEIVE_INTERRUPT USART1_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_URSEL URSEL0
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_CONTROLC UCSR1C
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#define UART1_UBRRL UBRR1L
#define UART1_UBRRH UBRR1H
#define UART1_BIT_URSEL URSEL1
#define UART1_BIT_U2X U2X1
#define UART1_BIT_RXCIE RXCIE1
#define UART1_BIT_RXEN RXEN1
#define UART1_BIT_TXEN TXEN1
#define UART1_BIT_UCSZ0 UCSZ10
#define UART1_BIT_UCSZ1 UCSZ11
#elif defined(__AVR_ATmega161__)
/* ATmega with UART */
#error "AVR ATmega161 currently not supported by this libaray !"
#elif defined(__AVR_ATmega169__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega48PB__) || \
defined(__AVR_ATmega88__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega88PB__) || \
defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__)|| defined(__AVR_ATmega168P__)|| defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || \
defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || \
defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3290__) ||defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__) || defined(__AVR_ATtiny4313__)
/* ATtiny with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#elif defined(__AVR_ATmega329__) || defined(__AVR_ATmega649__) || defined(__AVR_ATmega3290__) || defined(__AVR_ATmega6490__) ||\
defined(__AVR_ATmega169A__) || defined(__AVR_ATmega169PA__) || \
defined(__AVR_ATmega329A__) || defined(__AVR_ATmega329PA__) || defined(__AVR_ATmega3290A__) || defined(__AVR_ATmega3290PA__) || \
defined(__AVR_ATmega649A__) || defined(__AVR_ATmega649P__) || defined(__AVR_ATmega6490A__) || defined(__AVR_ATmega6490P__) || \
defined(__AVR_ATmega165__) || defined(__AVR_ATmega325__) || defined(__AVR_ATmega645__) || defined(__AVR_ATmega3250__) || defined(__AVR_ATmega6450__) || \
defined(__AVR_ATmega165A__) || defined(__AVR_ATmega165PA__) || \
defined(__AVR_ATmega325A__) || defined(__AVR_ATmega325PA__) || defined(__AVR_ATmega3250A__) || defined(__AVR_ATmega3250PA__) ||\
defined(__AVR_ATmega645A__) || defined(__AVR_ATmega645PA__) || defined(__AVR_ATmega6450A__) || defined(__AVR_ATmega6450PA__) || \
defined(__AVR_ATmega644__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega128A__) ||\
defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || \
defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__) || \
defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164PA__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) || \
defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) ||\
defined(__AVR_ATtiny1634__)
/* ATmega with two USART */
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_CONTROLC UCSR1C
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#define UART1_UBRRL UBRR1L
#define UART1_UBRRH UBRR1H
#define UART1_BIT_U2X U2X1
#define UART1_BIT_RXCIE RXCIE1
#define UART1_BIT_RXEN RXEN1
#define UART1_BIT_TXEN TXEN1
#define UART1_BIT_UCSZ0 UCSZ10
#define UART1_BIT_UCSZ1 UCSZ11
#elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || \
defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \
defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)
#define UART0_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR1A
#define UART0_CONTROL UCSR1B
#define UART0_CONTROLC UCSR1C
#define UART0_DATA UDR1
#define UART0_UDRIE UDRIE1
#define UART0_UBRRL UBRR1L
#define UART0_UBRRH UBRR1H
#define UART0_BIT_U2X U2X1
#define UART0_BIT_RXCIE RXCIE1
#define UART0_BIT_RXEN RXEN1
#define UART0_BIT_TXEN TXEN1
#define UART0_BIT_UCSZ0 UCSZ10
#define UART0_BIT_UCSZ1 UCSZ11
#else
#error "no UART definition for MCU available"
#endif
/*
* module global variables
*/
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;
#if defined( ATMEGA_USART1 )
static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART1_TxHead;
static volatile unsigned char UART1_TxTail;
static volatile unsigned char UART1_RxHead;
static volatile unsigned char UART1_RxTail;
static volatile unsigned char UART1_LastRxError;
#endif
ISR (UART0_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART Receive Complete interrupt
Purpose: called when the UART has received a character
**************************************************************************/
{
unsigned char tmphead;
unsigned char data;
unsigned char usr;
unsigned char lastRxError;
/* read UART status register and UART data register */
usr = UART0_STATUS;
data = UART0_DATA;
/* get FEn (Frame Error) DORn (Data OverRun) UPEn (USART Parity Error) bits */
#if defined(FE) && defined(DOR) && defined(UPE)
lastRxError = usr & (_BV(FE)|_BV(DOR)|_BV(UPE) );
#elif defined(FE0) && defined(DOR0) && defined(UPE0)
lastRxError = usr & (_BV(FE0)|_BV(DOR0)|_BV(UPE0) );
#elif defined(FE1) && defined(DOR1) && defined(UPE1)
lastRxError = usr & (_BV(FE1)|_BV(DOR1)|_BV(UPE1) );
#elif defined(FE) && defined(DOR)
lastRxError = usr & (_BV(FE)|_BV(DOR) );
#endif
/* calculate buffer index */
tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
if ( tmphead == UART_RxTail ) {
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 8;
}else{
/* store new index */
UART_RxHead = tmphead;
/* store received data in buffer */
UART_RxBuf[tmphead] = data;
}
UART_LastRxError |= lastRxError;
}
ISR (UART0_TRANSMIT_INTERRUPT)
/*************************************************************************
Function: UART Data Register Empty interrupt
Purpose: called when the UART is ready to transmit the next byte
**************************************************************************/
{
unsigned char tmptail;
if ( UART_TxHead != UART_TxTail) {
/* calculate and store new buffer index */
tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail;
/* get one byte from buffer and write it to UART */
UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
}else{
/* tx buffer empty, disable UDRE interrupt */
UART0_CONTROL &= ~_BV(UART0_UDRIE);
}
}
/*************************************************************************
Function: uart_init()
Purpose: initialize UART and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart_init(unsigned int baudrate)
{
UART_TxHead = 0;
UART_TxTail = 0;
UART_RxHead = 0;
UART_RxTail = 0;
#ifdef UART_TEST
#ifndef UART0_BIT_U2X
#warning "UART0_BIT_U2X not defined"
#endif
#ifndef UART0_UBRRH
#warning "UART0_UBRRH not defined"
#endif
#ifndef UART0_CONTROLC
#warning "UART0_CONTROLC not defined"
#endif
#if defined(URSEL) || defined(URSEL0)
#ifndef UART0_BIT_URSEL
#warning "UART0_BIT_URSEL not defined"
#endif
#endif
#endif
/* Set baud rate */
if ( baudrate & 0x8000 )
{
#if UART0_BIT_U2X
UART0_STATUS = (1<<UART0_BIT_U2X); //Enable 2x speed
#endif
}
#if defined(UART0_UBRRH)
UART0_UBRRH = (unsigned char)((baudrate>>8)&0x80) ;
#endif
UART0_UBRRL = (unsigned char) (baudrate&0x00FF);
/* Enable USART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(UART0_BIT_RXCIE)|(1<<UART0_BIT_RXEN)|(1<<UART0_BIT_TXEN);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef UART0_CONTROLC
#ifdef UART0_BIT_URSEL
UART0_CONTROLC = (1<<UART0_BIT_URSEL)|(1<<UART0_BIT_UCSZ1)|(1<<UART0_BIT_UCSZ0);
#else
UART0_CONTROLC = (1<<UART0_BIT_UCSZ1)|(1<<UART0_BIT_UCSZ0);
#endif
#endif
}/* uart_init */
/*************************************************************************
Function: uart_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart_getc(void)
{
unsigned char tmptail;
unsigned char data;
unsigned char lastRxError;
if ( UART_RxHead == UART_RxTail ) {
return UART_NO_DATA; /* no data available */
}
/* calculate buffer index */
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
/* get data from receive buffer */
data = UART_RxBuf[tmptail];
lastRxError = UART_LastRxError;
/* store buffer index */
UART_RxTail = tmptail;
UART_LastRxError = 0;
return (lastRxError << 8) + data;
}/* uart_getc */
/*************************************************************************
Function: uart_putc()
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
**************************************************************************/
void uart_putc(unsigned char data)
{
unsigned char tmphead;
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
while ( tmphead == UART_TxTail ){
;/* wait for free space in buffer */
}
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
/* enable UDRE interrupt */
UART0_CONTROL |= _BV(UART0_UDRIE);
}/* uart_putc */
/*************************************************************************
Function: uart_puts()
Purpose: transmit string to UART
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart_puts(const char *s )
{
while (*s)
uart_putc(*s++);
}/* uart_puts */
/*************************************************************************
Function: uart_puts_p()
Purpose: transmit string from program memory to UART
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart_puts_p(const char *progmem_s )
{
register char c;
while ( (c = pgm_read_byte(progmem_s++)) )
uart_putc(c);
}/* uart_puts_p */
/*
* these functions are only for ATmegas with two USART
*/
#if defined( ATMEGA_USART1 )
ISR(UART1_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART1 Receive Complete interrupt
Purpose: called when the UART1 has received a character
**************************************************************************/
{
unsigned char tmphead;
unsigned char data;
unsigned char usr;
unsigned char lastRxError;
/* read UART status register and UART data register */
usr = UART1_STATUS;
data = UART1_DATA;
/* get FEn (Frame Error) DORn (Data OverRun) UPEn (USART Parity Error) bits */
lastRxError = usr & (_BV(FE1)|_BV(DOR1)|_BV(UPE1) );
/* calculate buffer index */
tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
if ( tmphead == UART1_RxTail ) {
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 8;
}else{
/* store new index */
UART1_RxHead = tmphead;
/* store received data in buffer */
UART1_RxBuf[tmphead] = data;
}
UART1_LastRxError |= lastRxError;
}
ISR(UART1_TRANSMIT_INTERRUPT)
/*************************************************************************
Function: UART1 Data Register Empty interrupt
Purpose: called when the UART1 is ready to transmit the next byte
**************************************************************************/
{
unsigned char tmptail;
if ( UART1_TxHead != UART1_TxTail) {
/* calculate and store new buffer index */
tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
UART1_TxTail = tmptail;
/* get one byte from buffer and write it to UART */
UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
}else{
/* tx buffer empty, disable UDRE interrupt */
UART1_CONTROL &= ~_BV(UART1_UDRIE);
}
}
/*************************************************************************
Function: uart1_init()
Purpose: initialize UART1 and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart1_init(unsigned int baudrate)
{
UART1_TxHead = 0;
UART1_TxTail = 0;
UART1_RxHead = 0;
UART1_RxTail = 0;
#ifdef UART_TEST
#ifndef UART1_BIT_U2X
#warning "UART1_BIT_U2X not defined"
#endif
#ifndef UART1_UBRRH
#warning "UART1_UBRRH not defined"
#endif
#ifndef UART1_CONTROLC
#warning "UART1_CONTROLC not defined"
#endif
#if defined(URSEL) || defined(URSEL1)
#ifndef UART1_BIT_URSEL
#warning "UART1_BIT_URSEL not defined"
#endif
#endif
#endif
/* Set baud rate */
if ( baudrate & 0x8000 )
{
#if UART1_BIT_U2X
UART1_STATUS = (1<<UART1_BIT_U2X); //Enable 2x speed
#endif
}
UART1_UBRRH = (unsigned char)((baudrate>>8)&0x80) ;
UART1_UBRRL = (unsigned char) baudrate;
/* Enable USART receiver and transmitter and receive complete interrupt */
UART1_CONTROL = _BV(UART1_BIT_RXCIE)|(1<<UART1_BIT_RXEN)|(1<<UART1_BIT_TXEN);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef UART1_BIT_URSEL
UART1_CONTROLC = (1<<UART1_BIT_URSEL)|(1<<UART1_BIT_UCSZ1)|(1<<UART1_BIT_UCSZ0);
#else
UART1_CONTROLC = (1<<UART1_BIT_UCSZ1)|(1<<UART1_BIT_UCSZ0);
#endif
}/* uart_init */
/*************************************************************************
Function: uart1_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart1_getc(void)
{
unsigned char tmptail;
unsigned int data;
unsigned char lastRxError;