Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
3d1a1f392e | |||
06af784482 | |||
60d4bee9a6 | |||
d6cce7d39c | |||
|
5d0ed0a5e2 | ||
5806903747 | |||
81affab6e2 | |||
363a294515 | |||
67f182fe2a | |||
e330e259a1 | |||
8bc7c6a4af | |||
50fd1f1004 | |||
cc2ebfe37b | |||
8624c085d0 | |||
41f5eac0a6 | |||
07b8628080 | |||
26209772e7 | |||
f2a4bb877c | |||
3f424f88a9 | |||
aa2622d8c8 | |||
c39347c317 | |||
0938c1025e | |||
73fef2af54 |
6
Makefile
6
Makefile
@ -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 util.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
|
||||||
|
|
||||||
@ -25,8 +25,10 @@ $(PRG).elf: $(OBJ)
|
|||||||
@echo
|
@echo
|
||||||
|
|
||||||
# dependency:
|
# dependency:
|
||||||
rgbyteclock.o: timer.o lcd.o rgbyteclock.h rtc.o spi.o ledcontroller.o util.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
|
||||||
|
52
lcd.c
52
lcd.c
@ -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,9 +114,9 @@ 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
|
||||||
@ -116,28 +125,41 @@ static inline void lcd_send_byte(uint8_t byte, uint8_t RS)
|
|||||||
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)
|
||||||
@ -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
248
led1642gw.c
Normal 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
30
led1642gw.h
Normal 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
28
led1642gw_config.h
Normal 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_
|
||||||
|
|
232
ledcontroller.c
232
ledcontroller.c
@ -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 led_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 led_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 led_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 ) {
|
if ( map_lednum_to_channels(lednum, &c_r, &c_g, &c_b) > 0 ) {
|
||||||
ledbuffer[c_r] = red;
|
led1642gw_set_channel(c_r, red);
|
||||||
ledbuffer[c_g] = green;
|
led1642gw_set_channel(c_g, green);
|
||||||
ledbuffer[c_b] = blue;
|
led1642gw_set_channel(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 led_set_channel(uint8_t channel, uint16_t value)
|
|
||||||
{
|
|
||||||
if (channel < NUM_LED_CHANNELS) {
|
|
||||||
ledbuffer[channel] = 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)
|
void led_clear(void)
|
||||||
{
|
{
|
||||||
memset(ledbuffer, 0x00, sizeof(ledbuffer));
|
led1642gw_clear();
|
||||||
led_flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 led_set_current_mode(uint8_t mode)
|
||||||
|
{
|
||||||
|
led1642gw_set_current_mode(mode);
|
||||||
|
led1642gw_flush_config();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 led_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 led_turn_all_on(void);
|
|
||||||
void led_turn_all(void);
|
|
||||||
void led_set_channel(uint8_t channel, uint16_t value);
|
|
||||||
void led_clear(void);
|
void led_clear(void);
|
||||||
|
void led_turn_all_on(void);
|
||||||
|
void led_turn_all_off(void);
|
||||||
|
void led_set_gain(uint8_t gain);
|
||||||
|
void led_set_current_mode(uint8_t mode);
|
||||||
|
|
||||||
#endif // LEDCONTROLLER_H
|
#endif // LEDCONTROLLER_H
|
||||||
|
|
||||||
|
23
main.c
23
main.c
@ -19,17 +19,30 @@
|
|||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void)
|
||||||
|
{
|
||||||
|
|
||||||
timer_init();
|
timer_init();
|
||||||
//rtc_init(0);
|
rtc_init(0);
|
||||||
//spi_slave_init();
|
//spi_slave_init();
|
||||||
led_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.
|
||||||
|
|
||||||
rgbyteclock();
|
rgbyteclock();
|
||||||
// rgbyteclock() should never end, but who knows...
|
// rgbyteclock() should never end, but who knows...
|
||||||
while(1);
|
while (1) { ; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
493
rgbyteclock.c
493
rgbyteclock.c
@ -1,488 +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 "ledcontroller.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define SEED_RNG 0
|
|
||||||
#define INIT 1
|
|
||||||
#define INTRO 2
|
|
||||||
#define INTRODUCE_COLORS 3
|
|
||||||
#define SHOW_SEQUENCE 4
|
|
||||||
#define GET_USER_SEQUENCE 5
|
|
||||||
#define USER_GUESS_OK 6
|
|
||||||
#define USER_GUESS_NOK 7
|
|
||||||
#define EXTEND_SEQUENCE 8
|
|
||||||
#define WIN 9
|
|
||||||
|
|
||||||
int8_t show_anim_sequence( uint32_t now, uint32_t animation_start );
|
void rgbyteclock(void)
|
||||||
int8_t show_intro( uint32_t now, uint32_t animation_start );
|
{
|
||||||
int8_t show_introduce_colors( uint32_t now, uint32_t animation_start );
|
uint8_t gain = 0x2f;
|
||||||
void show_anim_wait_seed( uint32_t now, uint32_t animation_start );
|
led_set_gain(gain);
|
||||||
int8_t show_anim_ok( uint32_t now, uint32_t animation_start );
|
while (1) {
|
||||||
int8_t show_anim_nok( uint32_t now, uint32_t animation_start );
|
|
||||||
int8_t get_sequence( uint32_t now, uint32_t animation_start );
|
|
||||||
int8_t show_anim_win( uint32_t now, uint32_t animation_start );
|
|
||||||
|
|
||||||
|
led_set(0, 4000, 0, 0);
|
||||||
|
led_flush();
|
||||||
|
timer_wait(500);
|
||||||
|
|
||||||
static uint8_t sequence[12];
|
led_set(1, 0, 10000, 0);
|
||||||
static uint8_t sequence_index;
|
led_flush();
|
||||||
static uint8_t input_sequence_index;
|
timer_wait(500);
|
||||||
static uint8_t colorScheme[2];
|
|
||||||
|
|
||||||
void rgbyteclock(void) {
|
led_set(0, 0, 0, 0);
|
||||||
uint32_t now, t1;
|
led_flush();
|
||||||
int8_t end;
|
timer_wait(500);
|
||||||
uint8_t button = BUTTON_NONE;
|
|
||||||
|
|
||||||
uint8_t gameState = SEED_RNG;
|
led_set(1, 0, 0, 0);
|
||||||
|
led_flush();
|
||||||
|
timer_wait(500);
|
||||||
|
|
||||||
led_turn_all_on();
|
PORTC ^= (1<<PC5); // Test LED
|
||||||
|
|
||||||
t1 = 0;
|
|
||||||
while ( 1 ) {
|
|
||||||
now = timer_get( );
|
|
||||||
|
|
||||||
switch( gameState ) {
|
|
||||||
|
|
||||||
case SEED_RNG:
|
|
||||||
// get seed for RNG from button press
|
|
||||||
show_anim_wait_seed( now, t1 );
|
|
||||||
button = get_button( );
|
|
||||||
|
|
||||||
if( button != BUTTON_NONE ) {
|
|
||||||
init_random( (uint16_t)(now - t1));
|
|
||||||
gameState = INIT;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INIT:
|
|
||||||
sequence_index = 0;
|
|
||||||
input_sequence_index = 0;
|
|
||||||
gameState = INTRO;
|
|
||||||
|
|
||||||
colorScheme[0] = (random()%6) +1;
|
|
||||||
colorScheme[1] = colorScheme[0];
|
|
||||||
|
|
||||||
while( colorScheme[0] == colorScheme[1] ) {
|
|
||||||
colorScheme[1] = (random()%6) +1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// all buttons dark
|
|
||||||
for( int i=12; i<14; i++ ) {
|
|
||||||
led_set( i, 0,0,0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
t1 = now;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INTRO:
|
|
||||||
// show a nice animation to indicate the start of the game
|
|
||||||
end = show_intro( now, t1 );
|
|
||||||
if( end ) {
|
|
||||||
gameState = INTRODUCE_COLORS;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INTRODUCE_COLORS:
|
|
||||||
end = show_introduce_colors( now, t1 );
|
|
||||||
if( end ) {
|
|
||||||
gameState = EXTEND_SEQUENCE;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHOW_SEQUENCE:
|
|
||||||
end = show_anim_sequence( now, t1 );
|
|
||||||
|
|
||||||
if( end == 1 ) {
|
|
||||||
gameState = GET_USER_SEQUENCE;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_USER_SEQUENCE:
|
|
||||||
end = get_sequence( now, t1 );
|
|
||||||
|
|
||||||
if( end == 1 ) {
|
|
||||||
gameState = USER_GUESS_NOK;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( end == 2 ) {
|
|
||||||
gameState = USER_GUESS_OK;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case USER_GUESS_OK:
|
|
||||||
end = show_anim_ok( now, t1 );
|
|
||||||
if( end ) {
|
|
||||||
gameState = EXTEND_SEQUENCE;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case USER_GUESS_NOK:
|
|
||||||
end = show_anim_nok( now, t1 );
|
|
||||||
if( end ) {
|
|
||||||
gameState = INIT;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXTEND_SEQUENCE:
|
|
||||||
|
|
||||||
if(sequence_index >= 12) {
|
|
||||||
gameState = WIN;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gameState = SHOW_SEQUENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( random()&1 ) {
|
|
||||||
sequence[sequence_index] = colorScheme[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sequence[sequence_index] = colorScheme[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence_index++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WIN:
|
|
||||||
end = show_anim_win( now, t1 );
|
|
||||||
|
|
||||||
if( end ) {
|
|
||||||
gameState = INIT;
|
|
||||||
t1 = now;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
led_flush( );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t get_sequence( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint16_t r,g,b;
|
|
||||||
uint8_t button;
|
|
||||||
uint8_t color;
|
|
||||||
uint8_t guessOK;
|
|
||||||
|
|
||||||
button = get_button( );
|
|
||||||
color = sequence[input_sequence_index];
|
|
||||||
guessOK = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if( button == BUTTON_RO ) {
|
|
||||||
if( color == colorScheme[0] ) {
|
|
||||||
guessOK = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( button == BUTTON_LO ) {
|
|
||||||
if( color == colorScheme[1] ) {
|
|
||||||
guessOK = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( guessOK ) {
|
|
||||||
// draw what user entered until now
|
|
||||||
get_color( &r, &g, &b, color );
|
|
||||||
led_set( input_sequence_index, r, g, b );
|
|
||||||
|
|
||||||
input_sequence_index++;
|
|
||||||
|
|
||||||
if( input_sequence_index >= sequence_index) {
|
|
||||||
input_sequence_index = 0;
|
|
||||||
return 2; // entire sequence right
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; // right but not finished
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1; // user guessed wrong
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
##############
|
|
||||||
# ANIMATIONS #
|
|
||||||
##############
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t show_anim_sequence( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint32_t t_diff = now - animation_start;
|
|
||||||
uint16_t r,g,b;
|
|
||||||
uint8_t tmp_index;
|
|
||||||
const uint16_t holdTime=1000 /*ms*/, stepSpeed=500 /*ms*/;
|
|
||||||
|
|
||||||
tmp_index = (t_diff/stepSpeed) +1;
|
|
||||||
|
|
||||||
if( tmp_index > sequence_index ) {
|
|
||||||
tmp_index = sequence_index;
|
|
||||||
}
|
|
||||||
for( int i=0; i<tmp_index; i++ ) {
|
|
||||||
get_color( &r, &g, &b, sequence[i] );
|
|
||||||
led_set( i, r, g, b );
|
|
||||||
}
|
|
||||||
|
|
||||||
// display last color for 2 seconds
|
|
||||||
if( t_diff > (sequence_index * stepSpeed)+holdTime ) {
|
|
||||||
// hide sequence
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
get_color( &r, &g, &b, COLOR_BLACK );
|
|
||||||
led_set( i, r, g, b);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t show_introduce_colors( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint32_t t_diff = now - animation_start;
|
|
||||||
uint16_t r,g,b;
|
|
||||||
|
|
||||||
// all ring LEDs off
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0,0,0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( t_diff%100 < 50 ) {
|
|
||||||
// put gamecolors on the buttons
|
|
||||||
get_color( &r, &g, &b, colorScheme[0] );
|
|
||||||
led_set( 12, r, g, b); // RO
|
|
||||||
get_color( &r, &g, &b, colorScheme[1] );
|
|
||||||
led_set( 13, r, g, b); // LO
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for( int i=12; i<14; i++ ) {
|
|
||||||
get_color( &r, &g, &b, COLOR_BLACK );
|
|
||||||
led_set( i, r,g,b );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( t_diff > 1000 ) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void show_anim_wait_seed( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint32_t t_diff = (now - animation_start)%1000;
|
|
||||||
uint16_t w;
|
|
||||||
|
|
||||||
if( t_diff < 500 ) {
|
|
||||||
// fade up
|
|
||||||
w = (MAX_BRIGHTNESS/500) * t_diff;
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, w, w, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// fade down
|
|
||||||
w = MAX_BRIGHTNESS - (MAX_BRIGHTNESS/500) * (t_diff-500);
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, w, w, w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t show_intro( uint32_t now, uint32_t animation_start ) {
|
|
||||||
// Animation: rotate a single LED once across the circle
|
|
||||||
uint32_t t_diff = now - animation_start;
|
|
||||||
uint16_t r,g,b;
|
|
||||||
uint8_t index;
|
|
||||||
static uint8_t tmp_sequence[12], tmp;
|
|
||||||
static uint8_t step = 0;
|
|
||||||
|
|
||||||
if( step == 0) {
|
|
||||||
for( int i=0; i<12; i++) {
|
|
||||||
tmp_sequence[i] = (random()%6)+1;
|
|
||||||
}
|
|
||||||
step = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = (t_diff%1200)/100;
|
|
||||||
|
|
||||||
// print a chain of random colors
|
|
||||||
if( !(t_diff % 100) && (step == 1) ) {
|
|
||||||
// every 100ms
|
|
||||||
get_color( &r, &g, &b, tmp_sequence[index] );
|
|
||||||
led_set( index, r, g, b );
|
|
||||||
|
|
||||||
// goto next animation sequence
|
|
||||||
if( t_diff > 1200 ) {
|
|
||||||
step = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// rotate chain 180 degrees
|
|
||||||
if( !(t_diff % 100) && (step == 2) ) {
|
|
||||||
// barrelshift every 100ms
|
|
||||||
tmp = tmp_sequence[11];
|
|
||||||
for( int i=10; i>=0; i-- ) {
|
|
||||||
tmp_sequence[i+1] = tmp_sequence[i];
|
|
||||||
}
|
|
||||||
tmp_sequence[0] = tmp;
|
|
||||||
|
|
||||||
// update all at once
|
|
||||||
for(int i=0; i<12; i++ ) {
|
|
||||||
get_color( &r, &g, &b, tmp_sequence[i] );
|
|
||||||
led_set( i, r, g, b );
|
|
||||||
}
|
|
||||||
if( t_diff > 2400 ) {
|
|
||||||
step = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// overwite step by step with button colors
|
|
||||||
if( !(t_diff % 100) && (step == 3) ) {
|
|
||||||
for( int i=0; i<index; i++ ) {
|
|
||||||
get_color( &r, &g, &b, colorScheme[0] );
|
|
||||||
led_set( i, r, g, b );
|
|
||||||
|
|
||||||
get_color( &r, &g, &b, colorScheme[1] );
|
|
||||||
led_set( i+6, r, g, b );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( t_diff > 2900 ) {
|
|
||||||
step = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( step == 4) {
|
|
||||||
// blank top and bottom LED for symetry
|
|
||||||
led_set( 0, 0, 0, 0 );
|
|
||||||
led_set( 6, 0, 0, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (now - animation_start) > 4000 ) {
|
|
||||||
step = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t show_anim_ok( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint32_t t_diff = now - animation_start;
|
|
||||||
uint16_t g;
|
|
||||||
|
|
||||||
if( t_diff < 500 ) {
|
|
||||||
g = (MAX_BRIGHTNESS/500) * t_diff;
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, g, 0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g = MAX_BRIGHTNESS - (MAX_BRIGHTNESS/500) * (t_diff-500);
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, g, 0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( t_diff > 1000 ) {
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, 0x00, 0x00);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t show_anim_nok( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint32_t t_diff = now - animation_start;
|
|
||||||
uint16_t r,g,b;
|
|
||||||
|
|
||||||
if( t_diff%100 < 50 ) {
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
get_color( &r, &g, &b, COLOR_RED );
|
|
||||||
led_set( i, r,g,b );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
get_color( &r, &g, &b, COLOR_BLACK );
|
|
||||||
led_set( i, r,g,b );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( t_diff > 1000 ) {
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, 0x00, 0x00);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t show_anim_win( uint32_t now, uint32_t animation_start ) {
|
|
||||||
uint32_t t_diff = now - animation_start;
|
|
||||||
uint16_t b;
|
|
||||||
|
|
||||||
if( t_diff < 1000 ) {
|
|
||||||
b = (MAX_BRIGHTNESS/1000) * t_diff;
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, 0x00, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b = MAX_BRIGHTNESS - (MAX_BRIGHTNESS/1000) * (t_diff-1000);
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, 0x00, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if( t_diff > 2000 ) {
|
|
||||||
for( int i=0; i<12; i++ ) {
|
|
||||||
led_set( i, 0x00, 0x00, 0x00);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -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
5
rtc.c
@ -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
|
||||||
|
2
timer.c
2
timer.c
@ -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
|
||||||
|
104
util.c
104
util.c
@ -1,104 +0,0 @@
|
|||||||
#include <avr/io.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static volatile uint16_t s_lfsr=0xACE1u;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void init_random( uint16_t lfsr ) {
|
|
||||||
s_lfsr = lfsr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t random( void ) {
|
|
||||||
uint8_t bit;
|
|
||||||
|
|
||||||
bit = ((s_lfsr >> 0) ^ (s_lfsr >> 2) ^ (s_lfsr >> 3) ^ (s_lfsr >> 5) ) & 1;
|
|
||||||
s_lfsr = (s_lfsr >> 1) | (bit << 15);
|
|
||||||
return s_lfsr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void get_color( uint16_t *r, uint16_t *g, uint16_t *b, uint8_t colorIndex ) {
|
|
||||||
switch( colorIndex ) {
|
|
||||||
case COLOR_RED:
|
|
||||||
*r = MAX_BRIGHTNESS;
|
|
||||||
*g = 0x00;
|
|
||||||
*b = 0x00;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COLOR_GREEN:
|
|
||||||
*r = 0x00;
|
|
||||||
*g = MAX_BRIGHTNESS;
|
|
||||||
*b = 0x00;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COLOR_YELLOW:
|
|
||||||
*r = MAX_BRIGHTNESS;
|
|
||||||
*g = MAX_BRIGHTNESS;
|
|
||||||
*b = 0x00;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COLOR_BLUE:
|
|
||||||
*r = 0x00;
|
|
||||||
*g = 0x00;
|
|
||||||
*b = MAX_BRIGHTNESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COLOR_MAGENTA:
|
|
||||||
*r = MAX_BRIGHTNESS;
|
|
||||||
*g = 0x00;
|
|
||||||
*b = MAX_BRIGHTNESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COLOR_CYAN:
|
|
||||||
*r = 0x00;
|
|
||||||
*g = MAX_BRIGHTNESS;
|
|
||||||
*b = MAX_BRIGHTNESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COLOR_WHITE:
|
|
||||||
*r = MAX_BRIGHTNESS;
|
|
||||||
*g = MAX_BRIGHTNESS;
|
|
||||||
*b = MAX_BRIGHTNESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // black
|
|
||||||
*r = 0x00;
|
|
||||||
*g = 0x00;
|
|
||||||
*b = 0x00;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t get_button( void ) {
|
|
||||||
static uint8_t last_button = BUTTON_NONE;
|
|
||||||
uint8_t button = BUTTON_NONE;
|
|
||||||
|
|
||||||
if( !(PIND&(1<<PD5)) )
|
|
||||||
button = BUTTON_LU;
|
|
||||||
|
|
||||||
if( !(PIND&(1<<PD6)) )
|
|
||||||
button = BUTTON_LO;
|
|
||||||
|
|
||||||
if( !(PIND&(1<<PD7)) )
|
|
||||||
button = BUTTON_RO;
|
|
||||||
|
|
||||||
if( !(PINB&(1<<PB0)) )
|
|
||||||
button = BUTTON_RU;
|
|
||||||
|
|
||||||
|
|
||||||
if( button != last_button ) {
|
|
||||||
last_button = button;
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
return BUTTON_NONE;
|
|
||||||
|
|
||||||
}
|
|
22
util.h
22
util.h
@ -1,22 +0,0 @@
|
|||||||
#define MAX_BRIGHTNESS 0x0800
|
|
||||||
|
|
||||||
#define COLOR_BLACK 0
|
|
||||||
#define COLOR_RED 1
|
|
||||||
#define COLOR_GREEN 2
|
|
||||||
#define COLOR_YELLOW 3
|
|
||||||
#define COLOR_BLUE 4
|
|
||||||
#define COLOR_MAGENTA 5
|
|
||||||
#define COLOR_CYAN 6
|
|
||||||
#define COLOR_WHITE 7
|
|
||||||
|
|
||||||
|
|
||||||
#define BUTTON_NONE 0
|
|
||||||
#define BUTTON_LU 1
|
|
||||||
#define BUTTON_LO 2
|
|
||||||
#define BUTTON_RU 3
|
|
||||||
#define BUTTON_RO 4
|
|
||||||
|
|
||||||
void init_random( uint16_t lfsr );
|
|
||||||
uint16_t random( void );
|
|
||||||
void get_color( uint16_t *r, uint16_t *g, uint16_t *b, uint8_t colorIndex );
|
|
||||||
uint8_t get_button( void );
|
|
Loading…
Reference in New Issue
Block a user