rgbyteclock-code/ledcontroller.c

118 lines
2.5 KiB
C

/*
* ----------------------------------------------------------------------------
* "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 "ledcontroller.h"
#include <string.h>
#define NUM_LED1642GW_ICs (3)
#define NUM_LED1642GW_CHANNELS (16)
#define NUM_CHANNELS (NUM_LED1642GW_CHANNELS*NUM_LED1642GW_ICs)
static uint16_t ledbuffer[NUM_CHANNELS];
static int8_t get_channel_from_lednum(uint8_t lednum, uint8_t *channel_r, uint8_t *channel_g, uint8_t *channel_b)
{
uint8_t ret;
if (lednum < 15) {
*channel_r = 3*lednum;
*channel_g = 3*lednum+1;
*channel_b = 3*lednum+2;
if ( lednum >= 10 ) {
*channel_r += 2;
*channel_g += 2;
*channel_b += 2;
}
else if ( lednum >= 5 ) {
*channel_r += 1;
*channel_g += 1;
*channel_b += 1;
}
ret = 1;
}
else {
ret = 0;
}
return ret;
}
static void write_data(uint16_t data, uint8_t le_clocks)
{
PORTC &= ~(1<<PC3);
PORTC &= ~(1<<PC2);
uint16_t mask = 0x8000;
int8_t bit;
for (bit=15; bit>=le_clocks; bit--) {
if(data&mask) { PORTC |= (1<<PC4); }
else { PORTC &= ~(1<<PC4); }
PORTC |= (1<<PC3);
PORTC &= ~(1<<PC3);
mask >>= 1;
}
PORTC |= (1<<PC2);
for (/*noting to initialize*/; bit>=0; bit--) {
if(data&mask) { PORTC |= (1<<PC4); }
else { PORTC &= ~(1<<PC4); }
PORTC |= (1<<PC3);
PORTC &= ~(1<<PC3);
mask >>= 1;
}
}
static void write_data_latch(uint16_t data)
{
write_data(data, 4);
}
static void write_global_latch(uint16_t data)
{
write_data(data, 6);
}
void ledcontroller_init(void)
{
DDRC |= (1<<PC3); // SCK
DDRC |= (1<<PC4); // DATA
DDRC |= (1<<PC2); // LE
PORTC |= (1<<PC3); // SCK
PORTC |= (1<<PC4); // DATA
PORTC |= (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)
{
uint8_t c_r, c_g, c_b;
if ( get_channel_from_lednum(lednum, &c_r, &c_g, &c_b) > 0 ) {
ledbuffer[c_r] = red;
ledbuffer[c_g] = green;
ledbuffer[c_b] = blue;
}
}
void led_flush(void)
{
for (uint8_t i=0; i<NUM_CHANNELS-1; i++) {
write_data_latch(ledbuffer[i]);
}
write_global_latch(ledbuffer[NUM_CHANNELS-1]);
}