Compare commits

...

23 Commits

Author SHA1 Message Date
3d1a1f392e change wrong naming in comment 2015-01-09 03:12:11 +01:00
06af784482 fix off by one. should now work again 2015-01-09 03:09:48 +01:00
60d4bee9a6 changed flush function in led1642gw, hope this is easier to understand 2015-01-05 04:17:07 +01:00
d6cce7d39c write default values for configuration to LED1642GW 2014-08-15 22:42:58 +02:00
Nick Singer
5d0ed0a5e2 Added HSV support 2014-08-07 17:38:08 +02:00
5806903747 function prototye for set_current_mode 2014-06-23 03:54:00 +02:00
81affab6e2 only a few changes to led1642gw code 2014-06-23 03:39:43 +02:00
363a294515 more sensible default behaviour in default branch 2014-05-28 23:02:09 +02:00
67f182fe2a implemented gain and current mode settings 2014-04-17 04:15:15 +02:00
e330e259a1 make led1642gw.c more generic 2014-04-16 22:43:21 +02:00
8bc7c6a4af program faster. (only works with newer versions of megahidprog) 2014-03-20 01:27:38 +01:00
50fd1f1004 lcd_locate is useless, if not initialized 2014-03-19 03:51:25 +01:00
cc2ebfe37b implement timeout in LCD code 2014-03-19 03:49:57 +01:00
8624c085d0 there's a setfuses target in the makefile now 2014-03-19 03:24:08 +01:00
41f5eac0a6 document the LED1642GW and ledcontroller modules 2014-03-18 02:09:21 +01:00
07b8628080 put application specific config for led1642 into separate header file 2014-03-18 01:19:43 +01:00
26209772e7 remove old port definitions and fix missing include 2014-03-18 01:14:19 +01:00
f2a4bb877c make led1642 interface more generic 2014-03-18 01:04:18 +01:00
3f424f88a9 start with empty rgbyteclock.c 2014-03-15 15:34:37 +01:00
aa2622d8c8 ledcontroller: rename ledcontroller_ prefix in functions to led_ 2014-03-15 00:18:40 +01:00
c39347c317 one more pattern 2014-03-14 22:05:42 +01:00
0938c1025e better visible LED steps 2014-03-14 11:34:51 +01:00
73fef2af54 some basic patters. with bugs included. 2014-03-14 03:21:39 +01:00
12 changed files with 531 additions and 213 deletions

View File

@ -1,5 +1,5 @@
PRG = rgbyteclock PRG = rgbyteclock
OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o spi.o ringbuffer.o crc.o ledcontroller.o OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o spi.o ringbuffer.o crc.o ledcontroller.o led1642gw.o
MCU_TARGET = atmega164a MCU_TARGET = atmega164a
OPTIMIZE = -Os OPTIMIZE = -Os
@ -27,6 +27,8 @@ $(PRG).elf: $(OBJ)
# dependency: # dependency:
rgbyteclock.o: timer.o lcd.o rgbyteclock.h rtc.o spi.o ledcontroller.o rgbyteclock.o: timer.o lcd.o rgbyteclock.h rtc.o spi.o ledcontroller.o
main.o: rgbyteclock.o lcd.o spi.o ledcontroller.o rtc.o timer.o main.o: rgbyteclock.o lcd.o spi.o ledcontroller.o rtc.o timer.o
ledcontroller.o: led1642gw.o
led1642gw.o: led1642gw.h led1642gw_config.h
timer.o: timer.h timer.o: timer.h
lcd.o: lcd.h timer.o lcd.o: lcd.h timer.o
rtc.o: rtc.h rtc.o: rtc.h
@ -49,5 +51,9 @@ bin: $(PRG).bin
$(OBJCOPY) -j .text -j .data -O binary $< $@ $(OBJCOPY) -j .text -j .data -O binary $< $@
prg: $(PRG).bin prg: $(PRG).bin
python2 ../megaHidProg/megaHidProg.py -C -c 1000 -t 4 -b $(PRG).bin #python2 megaHidProg.py -C -c 1000 -t 4 -b $(PRG).bin
python2 ./megaHidProg.py -C -c 3000 -t 15 -b $(PRG).bin -T 15 -V $(PRG).bin
setfuses:
python2 megaHidProg.py -C -S -c 125 -L be -H d9 -E FC

72
lcd.c
View File

@ -50,6 +50,10 @@
// !!!!!!! // !!!!!!!
#define T_TIMEOUT (10)
static uint8_t lcd_initialized;
static inline uint8_t lcd_read_byte(uint8_t RS) static inline uint8_t lcd_read_byte(uint8_t RS)
{ {
@ -79,14 +83,19 @@ static inline uint8_t lcd_read_byte(uint8_t RS)
} }
static inline void lcd_wait_while_busy(void) static inline int8_t lcd_wait_while_busy(void)
{ {
uint8_t byte; uint8_t byte;
uint32_t t_enter = timer_get();
do { do {
if (timer_get() > t_enter + T_TIMEOUT) {
return 0;
}
byte = lcd_read_byte(0); byte = lcd_read_byte(0);
} while (byte & 0x80); } while (byte & 0x80);
return; return 1;
} }
@ -105,46 +114,59 @@ static inline void send_nibble(uint8_t nibble)
* \param byte The byte to send to the LCD * \param byte The byte to send to the LCD
* \param RS specifies whether byte sent is data (RS==1) or command (RS==0) * \param RS specifies whether byte sent is data (RS==1) or command (RS==0)
*/ */
static inline void lcd_send_byte(uint8_t byte, uint8_t RS) static inline int8_t lcd_send_byte(uint8_t byte, uint8_t RS)
{ {
lcd_wait_while_busy(); if (lcd_wait_while_busy() ) {
if (RS) if (RS)
LCD_DATA_MODE(); LCD_DATA_MODE();
else else
LCD_CMD_MODE(); LCD_CMD_MODE();
send_nibble(byte >> 4); send_nibble(byte >> 4);
_NOP(); _NOP();
send_nibble(0x0f & byte); send_nibble(0x0f & byte);
return 1;
}
return 0;
} }
int lcd_get(void) int lcd_get(void)
{ {
lcd_wait_while_busy(); if ( lcd_wait_while_busy() ) {
return lcd_read_byte(1); return lcd_read_byte(1);
}
return -1;
} }
int lcd_put(char c) int lcd_put(char c)
{ {
lcd_send_byte(c, 1); if (!lcd_initialized) {
return 0; return 0;
}
return lcd_send_byte(c, 1);
} }
void lcd_puts(char *s) void lcd_puts(char *s)
{ {
if (!lcd_initialized) {
return;
}
while (*s) { while (*s) {
//lcd_put(*s++); //lcd_put(*s++);
lcd_send_byte(*s++, 1); if (!lcd_send_byte(*s++, 1)) {
return;
}
} }
return;
} }
void lcd_cursor(uint8_t blink) void lcd_cursor(uint8_t blink)
{ {
if (blink) { if (blink) {
// enable display with cursor + blinking // enable display with cursor + blinking
lcd_send_byte(0x0f, 0); lcd_send_byte(0x0f, 0);
} }
else { else {
// enable display, no cursor, no blinking // enable display, no cursor, no blinking
@ -160,6 +182,8 @@ void lcd_init(void)
* display we be set to 4-bit data mode * display we be set to 4-bit data mode
*/ */
lcd_initialized = 0;
// wait until LCD gets ready to accept instructions. // wait until LCD gets ready to accept instructions.
timer_wait(50); timer_wait(50);
@ -189,7 +213,11 @@ void lcd_init(void)
// set to 5 x 8 dots per character, // set to 5 x 8 dots per character,
// 16 characters per line, 2 lines // 16 characters per line, 2 lines
lcd_send_byte(0x28, 0); int success = lcd_send_byte(0x28, 0);
if ( !success ) {
return;
}
// enable display, no cursor, no blinking // enable display, no cursor, no blinking
//lcd_send_byte(0x0c, 0); //lcd_send_byte(0x0c, 0);
@ -205,6 +233,8 @@ void lcd_init(void)
// clear dislay // clear dislay
lcd_clear(); lcd_clear();
lcd_initialized = 1;
return; return;
} }
@ -215,6 +245,10 @@ void lcd_clear(void)
void lcd_locate(uint8_t row, uint8_t col) void lcd_locate(uint8_t row, uint8_t col)
{ {
if (!lcd_initialized) {
return;
}
if (row) if (row)
col += 0x40; col += 0x40;
lcd_send_byte(0x80 + col, 0); lcd_send_byte(0x80 + col, 0);

248
led1642gw.c Normal file
View File

@ -0,0 +1,248 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <struppi@struppi.name> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return.
* (c) 2014 Stefan Rupp
* ----------------------------------------------------------------------------
*/
#include <string.h>
#include "led1642gw.h"
#include "led1642gw_config.h"
#define NUM_LED1642GW_CHANNELS (16) // number of LED channels per IC
//total numer of channels. needed to calculate the buffer size.
#define NUM_LED_CHANNELS (NUM_LED1642GW_CHANNELS*NUM_LED1642GW_ICs)
/* The buffer to hold the LED values.
* The data in this buffer can be manipulated with
* e.g. led1642gw_set().
* calling led1642gw_flush() sends the data in this buffer
* the data registers of the LED1642 ICs.
*/
static uint16_t ledbuffer[NUM_LED_CHANNELS];
static uint16_t config_reg[NUM_LED1642GW_ICs];
/*
* Write 16 bits of \data, with LE set high
* for the number of clock cycles specified in \le_clocks.
* MSB comes first, LSB is last.
*/
static void write_data(uint16_t data, uint8_t le_clocks)
{
uint16_t mask = 0x8000;
int8_t bit;
SET_CLK_L();
SET_LE_L();
for (bit=15; bit>=le_clocks; bit--) {
if(data&mask) { SET_SDI_H(); }
else { SET_SDI_L(); }
SET_CLK_H();
mask >>= 1;
SET_CLK_L();
}
SET_LE_H();
for (/*noting to initialize*/; bit>=0; bit--) {
if(data&mask) { SET_SDI_H(); }
else { SET_SDI_L(); }
SET_CLK_H();
mask >>= 1;
SET_CLK_L();
}
// set all pins to low after transmission
//SET_CLK_L();
SET_LE_L();
SET_SDI_L();
}
/*
* Write data to BRIGHTNESS DATA LATCH register.
* that means setting LE high for 3 or 4 clock cycles
*/
static void write_data_latch(uint16_t data)
{
write_data(data, 4);
}
/*
* Write data to BRIGHTNESS GLOBAL LATCH register.
* that means setting LE high for 5 or 6 clock cycles
*/
static void write_global_latch(uint16_t data)
{
write_data(data, 6);
}
/*
* This function shifts data through the 16bit shift
* register of the LED1642GW, without writing the data
* to any internal register of the IC.
* This way, we can daisy chain an bunch of LED1642GW ICs,
* and still get data through to any of those.
*/
static void write_no_command(uint16_t data)
{
write_data(data, 0);
}
/*
* Write data to CONFIG register.
* that means setting LE high for 7 clock cycles
*/
void led1642gw_flush_config()
{
uint8_t ic;
for (ic=0; ic<(NUM_LED1642GW_ICs-1); ic++) {
write_no_command(config_reg[ic]);
}
write_data(config_reg[ic], 7);
}
/*
* Turn all channels on, so the data in the DATA LATCH
* register affects the LEDs attached to the IC.
*/
void led1642gw_turn_all_on(void)
{
uint8_t ic;
for (ic=0; ic<(NUM_LED1642GW_ICs-1); ic++) {
write_no_command(0xffff);
}
write_data(0xffff, 2);
}
/*
* Turn all channels off,
*/
void led1642gw_turn_all_off(void)
{
uint8_t ic;
for (ic=0; ic<(NUM_LED1642GW_ICs-1); ic++) {
write_no_command(0x0000);
}
write_data(0x0000, 2);
}
void led1642gw_set_gain(uint8_t gain)
{
if (gain > 0x3f) {
gain = 0x3f;
}
uint16_t g = gain;
for (uint8_t ic=0; ic<(NUM_LED1642GW_ICs); ic++) {
config_reg[ic] &= ~(0x003f);
config_reg[ic] |= g;
}
}
void led1642gw_set_current_mode(uint8_t mode)
{
uint16_t mask = (1<<6);
for (uint8_t ic=0; ic<(NUM_LED1642GW_ICs); ic++) {
if (mode) { config_reg[ic] |= mask; }
else { config_reg[ic] &= ~mask; }
}
}
/*
* Initialize the pins of the ATMega processor
* to drive the data signals to the ICs
* and initialize the LED buffer to zero.
*/
void led1642gw_init(void)
{
SET_CLK_L();
SET_SDI_L();
SET_LE_L();
DDR_CLK |= (1<<PIN_CLK);
DDR_SDI |= (1<<PIN_SDI);
DDR_LE |= (1<<PIN_LE);
memset(ledbuffer, 0x00, sizeof(ledbuffer));
memset(config_reg, 0x00, sizeof(config_reg));
led1642gw_flush_config();
led1642gw_flush();
}
/*
* Transmit data from the ledbuffer to the BRIGHTNESS latches of
* the LED driver ICs.
* Let's assume, we have n LED1642GW ICs daisy chained. Then
* we write n-1 times with write_no_command, to shift all
* data through the 16bit shift registers of each of the ICs.
* Then we once write with write_data_latch to store the data
* in the BRIGHTNESS DATA registers of the respective ICs.
* We do this for all but the last set of brightness data,
* where we don't write to the DATA LATCH, but to the GLOBAL DATA LATCH.
*/
void led1642gw_flush(void)
{
uint8_t channel;
uint8_t ic;
// for each of the first 15 channels, do the following:
for (channel=0; channel<NUM_LED1642GW_CHANNELS; channel++) {
// shift data throught the first n-1 ICs with write_no_command
for (ic=0; ic<(NUM_LED1642GW_ICs-1); ic++) {
write_no_command(ledbuffer[channel+(NUM_LED1642GW_CHANNELS*ic)]);
}
// then, when the brightness data has propagated through the
// shift registers, write all data into the DATA LATCH of
// all of the ICs.
// for the 16th channel, we don't write to the DATA LATCH, but
// to the CLOBAL data latch.
// once more, we do the trick with write_no_command, to
// shift data through all the ICs
if (channel < NUM_LED1642GW_CHANNELS-1) {
write_data_latch(ledbuffer[channel+(NUM_LED1642GW_CHANNELS*ic)]);
}
else {
write_global_latch(ledbuffer[(ic*NUM_LED1642GW_CHANNELS)-1]);
}
}
}
void led1642gw_set_channel(uint8_t channel, uint16_t value)
{
if (channel < NUM_LED_CHANNELS) {
ledbuffer[channel] = value;
}
}
void led1642gw_clear(void)
{
memset(ledbuffer, 0x00, sizeof(ledbuffer));
}

30
led1642gw.h Normal file
View File

@ -0,0 +1,30 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <struppi@struppi.name> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return.
* (c) 2014 Stefan Rupp
* ----------------------------------------------------------------------------
*/
#ifndef LED1642GW_H_
#define LED1642GW_H_
#include <avr/io.h>
#include <stdint.h>
void led1642gw_init(void);
void led1642gw_turn_all_on(void);
void led1642gw_turn_all_off(void);
void led1642gw_flush(void);
void led1642gw_set_channel(uint8_t channel, uint16_t value);
void led1642gw_clear(void);
void led1642gw_flush_config(void);
void led1642gw_set_gain(uint8_t gain);
void led1642gw_set_current_mode(uint8_t mode);
#endif // LED1642GW_H_

28
led1642gw_config.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef LED1642GW_CONFIG_H_
#define LED1642GW_CONFIG_H_
#define NUM_LED1642GW_ICs (3)
#define DDR_CLK (DDRC)
#define PORT_CLK (PORTC)
#define PIN_CLK (3)
#define SET_CLK_H() ((PORT_CLK) |= (1<<(PIN_CLK)))
#define SET_CLK_L() ((PORT_CLK) &= ~(1<<(PIN_CLK)))
#define DDR_SDI (DDRC)
#define PORT_SDI (PORTC)
#define PIN_SDI (4)
#define SET_SDI_H() ((PORT_SDI) |= (1<<(PIN_SDI)))
#define SET_SDI_L() ((PORT_SDI) &= ~(1<<(PIN_SDI)))
#define DDR_LE (DDRC)
#define PORT_LE (PORTC)
#define PIN_LE (2)
#define SET_LE_H() ((PORT_LE) |= (1<<(PIN_LE)))
#define SET_LE_L() ((PORT_LE) &= ~(1<<(PIN_LE)))
#endif // LED1642GW_CONFIG_H_

View File

@ -17,16 +17,12 @@
*/ */
#include "ledcontroller.h" #include "ledcontroller.h"
#include <string.h> #include "led1642gw.h"
#include <util/delay.h>
#define NUM_LED1642GW_ICs (3)
#define NUM_LED1642GW_CHANNELS (16)
#define NUM_LED_CHANNELS (NUM_LED1642GW_CHANNELS*NUM_LED1642GW_ICs)
static uint16_t ledbuffer[NUM_LED_CHANNELS];
/*
* Application specific mapping of LEDs and there respective color channels
* to the respective channels of the three LED1642GW ICs.
*/
static int8_t map_lednum_to_channels(uint8_t lednum, uint8_t *channel_r, uint8_t *channel_g, uint8_t *channel_b) static int8_t map_lednum_to_channels(uint8_t lednum, uint8_t *channel_r, uint8_t *channel_g, uint8_t *channel_b)
{ {
uint8_t ret=0; uint8_t ret=0;
@ -114,127 +110,131 @@ static int8_t map_lednum_to_channels(uint8_t lednum, uint8_t *channel_r, uint8_t
} }
/*
static void write_data(uint16_t data, uint8_t le_clocks) * set one RGB LED to a RGB value.
{ * This only changes the Red, Green and Blue values in the
uint16_t mask = 0x8000; * internal LED buffer, the physical LED will still remain in its previous
int8_t bit; * state, until you call led_flush().
PORTC &= ~(1<<PC2); */
for (bit=15; bit>=le_clocks; bit--) {
PORTC &= ~(1<<PC3);
if(data&mask) { PORTC |= (1<<PC4); }
else { PORTC &= ~(1<<PC4); }
PORTC |= (1<<PC3);
mask >>= 1;
}
PORTC |= (1<<PC2);
for (/*noting to initialize*/; bit>=0; bit--) {
PORTC &= ~(1<<PC3);
if(data&mask) { PORTC |= (1<<PC4); }
else { PORTC &= ~(1<<PC4); }
PORTC |= (1<<PC3);
mask >>= 1;
}
PORTC &= ~(1<<PC3);
PORTC &= ~(1<<PC2);
PORTC &= ~(1<<PC4);
}
static void write_data_latch(uint16_t data)
{
write_data(data, 4);
}
static void write_global_latch(uint16_t data)
{
write_data(data, 6);
}
static void write_no_command(uint16_t data)
{
write_data(data, 0);
}
void ledcontroller_turn_all_on(void)
{
write_data(0xffff, 2);
_delay_us(10);
write_data(0xffff, 2);
_delay_us(10);
write_data(0xffff, 2);
_delay_us(10);
}
void ledcontroller_turn_all_off(void)
{
write_data(0x0000, 2);
_delay_us(10);
write_data(0x0000, 2);
_delay_us(10);
write_data(0x0000, 2);
_delay_us(10);
}
void ledcontroller_init(void)
{
PORTC &= ~(1<<PC3); // SCK
PORTC &= ~(1<<PC4); // DATA
PORTC &= ~(1<<PC2); // LE
DDRC |= (1<<PC3); // SCK
DDRC |= (1<<PC4); // DATA
DDRC |= (1<<PC2); // LE
memset(ledbuffer, 0x00, sizeof(ledbuffer));
led_flush();
}
void led_set(uint8_t lednum, uint16_t red, uint16_t green, uint16_t blue) void led_set(uint8_t lednum, uint16_t red, uint16_t green, uint16_t blue)
{ {
uint8_t c_r, c_g, c_b; uint8_t c_r, c_g, c_b;
if ( map_lednum_to_channels(lednum, &c_r, &c_g, &c_b) > 0 ) {
led1642gw_set_channel(c_r, red);
led1642gw_set_channel(c_g, green);
led1642gw_set_channel(c_b, blue);
}
if ( map_lednum_to_channels(lednum, &c_r, &c_g, &c_b) > 0 ) {
ledbuffer[c_r] = red;
ledbuffer[c_g] = green;
ledbuffer[c_b] = blue;
}
} }
void led_set_hsv(uint8_t lednum, uint16_t hue, uint8_t saturation, uint8_t value)
{
uint16_t red, green, blue;
//Calculate hue
if ( hue < 61 ) {
red = 255;
green = ( 425UL * hue ) / 100;
blue = 0;
} else if ( hue < 121 ) {
red = 255 - ( ( 425UL * ( hue - 60 ) ) / 100 );
green = 255;
blue = 0;
} else if ( hue < 181 ) {
red = 0;
green = 255;
blue = ( 425UL * ( hue - 120 ) ) / 100;
} else if ( hue < 241 ) {
red = 0;
green = 255 - ( ( 425UL * ( hue - 180 ) ) / 100 );
blue = 255;
} else if ( hue < 301 ) {
red = ( 425UL * ( hue - 240 ) ) / 100;
green = 0;
blue = 255;
} else if ( hue < 360) {
red = 255;
green = 0;
blue = 255 - ( ( 425UL * ( hue - 300 ) ) / 100);
}
//Calculate saturation
uint8_t diff;
saturation = 100 - saturation;
diff = ( ( 255 - red ) * saturation ) / 100;
red += diff;
diff = ( ( 255 - green ) * saturation ) / 100;
green += diff;
diff = ( ( 255 - blue ) * saturation ) / 100;
blue += diff;
//Calculate value
red = ( red * value ) / 100;
green = ( green * value ) / 100;
blue = ( blue * value ) / 100;
led_set(lednum, red<<8, green<<8, blue<<8);
}
/*
* Write the data stored in the LED buffers via led_set().
*/
void led_flush(void) void led_flush(void)
{ {
uint8_t channel; led1642gw_flush();
for (channel=0; channel<NUM_LED1642GW_CHANNELS-1; channel++) {
write_no_command(ledbuffer[channel+0]);
write_no_command(ledbuffer[channel+NUM_LED1642GW_CHANNELS]);
write_data_latch(ledbuffer[channel+(2*NUM_LED1642GW_CHANNELS)]);
}
write_no_command(ledbuffer[NUM_LED1642GW_CHANNELS-1]);
write_no_command(ledbuffer[(2*NUM_LED1642GW_CHANNELS)-1]);
write_global_latch(ledbuffer[(3*NUM_LED1642GW_CHANNELS)-1]);
} }
void ledcontroller_set_channel(uint8_t channel, uint16_t value) /*
* Clear the LED buffer.
* This function only affects the LED buffer, but not the LEDs, until
* you call led_flush().
*/
void led_clear(void)
{ {
if (channel < NUM_LED_CHANNELS) { led1642gw_clear();
ledbuffer[channel] = value; }
/*
* Initialize the leddriver.
* Must be called before any other function in this module.
*/
void led_init(void)
{
led1642gw_init();
}
/*
* Turn all channels on on every LED1642GW IC.
* If you don't turn the channels on, led_set
* won't have any effect, and the LEDs will remain dark.
*/
void led_turn_all_on(void)
{
led1642gw_turn_all_on();
}
void led_set_gain(uint8_t gain)
{
if (gain > 0x3f) {
gain = 0x3f;
} }
led1642gw_set_gain(gain);
led1642gw_flush_config();
} }
void ledcontroller_clear(void) void led_set_current_mode(uint8_t mode)
{ {
memset(ledbuffer, 0x00, sizeof(ledbuffer)); led1642gw_set_current_mode(mode);
led_flush(); led1642gw_flush_config();
} }

View File

@ -14,19 +14,17 @@
#define LEDCONTROLLER_H #define LEDCONTROLLER_H
#include <avr/io.h> #include <avr/io.h>
#include <compat/ina90.h> // ==> _NOP()
#include "timer.h" #include "timer.h"
void led_init(void);
void ledcontroller_init(void);
void led_set(uint8_t lednum, uint16_t red, uint16_t green, uint16_t blue); void led_set(uint8_t lednum, uint16_t red, uint16_t green, uint16_t blue);
void led_set_hsv(uint8_t lednum, uint16_t hue, uint8_t saturation, uint8_t value);
void led_flush(void); void led_flush(void);
void ledcontroller_turn_all_on(void); void led_clear(void);
void ledcontroller_turn_all(void); void led_turn_all_on(void);
void ledcontroller_set_channel(uint8_t channel, uint16_t value); void led_turn_all_off(void);
void ledcontroller_clear(void); void led_set_gain(uint8_t gain);
void led_set_current_mode(uint8_t mode);
#endif // LEDCONTROLLER_H #endif // LEDCONTROLLER_H

25
main.c
View File

@ -23,21 +23,24 @@ int main(void)
{ {
timer_init(); timer_init();
//rtc_init(0); rtc_init(0);
//spi_slave_init(); //spi_slave_init();
ledcontroller_init(); led_init();
sei(); sei();
//lcd_init();
DDRC |= (1<<PC5); lcd_init();
DDRC |= (1<<PC5); // Test LED
DDRD |= (1<<PD4); // Backlight
PORTD |= (1<<PD4);
lcd_puts("RGByteclock");
lcd_locate(1,0);
lcd_puts("www.bytewerk.org");
led_turn_all_on(); // turn all LED channels on.
/*
while (1) {
PORTC ^= (1<<PC5);
timer_wait(5000);
//_delay_ms(100);
}
*/
rgbyteclock(); rgbyteclock();
// rgbyteclock() should never end, but who knows... // rgbyteclock() should never end, but who knows...
while (1) { ; } while (1) { ; }

View File

@ -1,65 +1,31 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <struppi@struppi.name> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return.
* (c) 2014 Stefan Rupp
* ----------------------------------------------------------------------------
*/
#include "rgbyteclock.h" #include "rgbyteclock.h"
#include "timer.h"
#include "lcd.h"
#include "ledcontroller.h"
void rgbyteclock(void) void rgbyteclock(void)
{ {
uint8_t gain = 0x2f;
led_set_gain(gain);
while (1) {
ledcontroller_turn_all_on(); led_set(0, 4000, 0, 0);
led_flush();
timer_wait(500);
while (1) { led_set(1, 0, 10000, 0);
//PORTC ^= (1<<PC5); led_flush();
for (int i=0; i<14; i++) { timer_wait(500);
led_set(i, 0x7ff, 0x00, 0x00);
led_flush();
timer_wait(100);
}
/* for (int i=0; i<14; i++) { */
/* led_set(i, 0x00, 0x00, 0x00); */
/* } */
/* led_flush(); */
ledcontroller_clear();
timer_wait(100);
for (int i=0; i<14; i++) { led_set(0, 0, 0, 0);
led_set(i, 0x00, 0x7ff, 0x00); led_flush();
led_flush(); timer_wait(500);
timer_wait(100);
}
/* for (int i=0; i<14; i++) { */
/* led_set(i, 0x00, 0x00, 0x00); */
/* } */
/* led_flush(); */
ledcontroller_clear();
timer_wait(100);
for (int i=0; i<14; i++) { led_set(1, 0, 0, 0);
led_set(i, 0x00, 0x00, 0x7ff); led_flush();
led_flush(); timer_wait(500);
timer_wait(100);
}
/* for (int i=0; i<14; i++) { */
/* led_set(i, 0x00, 0x00, 0x00); */
/* } */
/* led_flush(); */
ledcontroller_clear();
timer_wait(100);
} PORTC ^= (1<<PC5); // Test LED
}
} }

View File

@ -14,7 +14,7 @@
#define RGBYTECLOCK_H #define RGBYTECLOCK_H
#include <avr/io.h> #include <avr/io.h>
#include "ledcontroller.h"
void rgbyteclock(void); void rgbyteclock(void);

5
rtc.c
View File

@ -22,6 +22,11 @@ ISR(TIMER2_OVF_vect) {
return; return;
} }
/*
* initialize the RTC module
* this resets the internal time to the value given in the
* rtc_time parameter
*/
void rtc_init(uint32_t rtc_time) void rtc_init(uint32_t rtc_time)
{ {
// Stop all interrupts // Stop all interrupts

View File

@ -46,7 +46,7 @@ void timer_init(void)
// ==> let timer count to 77 to get (almost) 1kHz frequency // ==> let timer count to 77 to get (almost) 1kHz frequency
// therefore: // therefore:
// - Set Timer/Counter0 prescaler to 256 ==> (1<<CS02) // - Set Timer/Counter0 prescaler to 256 ==> (1<<CS02)
// - Set OCR2 to 77 // - Set OCR0 to 77
// - CTC ( i.e. clear counter, when COUNTER == OCR0A) ==> (1<<WGM01) // - CTC ( i.e. clear counter, when COUNTER == OCR0A) ==> (1<<WGM01)
// unfortunately, due to the 20MHz and the coarse prescaler dividers // unfortunately, due to the 20MHz and the coarse prescaler dividers
// provided, we can't get any closer to the desired frequency of // provided, we can't get any closer to the desired frequency of