document the LED1642GW and ledcontroller modules

This commit is contained in:
Stefan Rupp 2014-03-18 02:09:21 +01:00
parent 07b8628080
commit 41f5eac0a6
2 changed files with 95 additions and 11 deletions

View File

@ -13,15 +13,29 @@
#include <string.h>
#include "led1642gw.h"
#include <util/delay.h>
#include "led1642gw_config.h"
#define NUM_LED1642GW_CHANNELS (16)
#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];
/*
* 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;
@ -43,7 +57,8 @@ static void write_data(uint16_t data, uint8_t le_clocks)
SET_CLK_H();
mask >>= 1;
}
// set all pins to low after transmission
SET_CLK_L();
SET_LE_L();
SET_SDI_L();
@ -51,46 +66,67 @@ static void write_data(uint16_t data, uint8_t le_clocks)
}
/*
* 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);
}
/*
* 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)
{
write_data(0xffff, 2);
_delay_us(10);
write_data(0xffff, 2);
_delay_us(10);
write_data(0xffff, 2);
_delay_us(10);
}
/*
* Turn all channels off,
*/
void led1642gw_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);
}
/*
* 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)
{
@ -105,19 +141,42 @@ void led1642gw_init(void)
}
/*
* 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-1; 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.
write_data_latch(ledbuffer[channel+(ic*NUM_LED1642GW_CHANNELS)]);
}
// 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
for (ic=1; ic<NUM_LED1642GW_ICs; ic++) {
write_no_command(ledbuffer[(ic*NUM_LED1642GW_CHANNELS)-1]);
}
// than, at last, write data to the global latch, to force
// the ICs to update their brightness data from the DATA LATCHES.
write_global_latch(ledbuffer[(ic*NUM_LED1642GW_CHANNELS)-1]);
}

View File

@ -19,7 +19,10 @@
#include "ledcontroller.h"
#include "led1642gw.h"
/*
* 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)
{
uint8_t ret=0;
@ -107,7 +110,12 @@ static int8_t map_lednum_to_channels(uint8_t lednum, uint8_t *channel_r, uint8_t
}
/*
* set one RGB LED to a RGB value.
* This only changes the Red, Green and Blue values in the
* internal LED buffer, the physical LED will still remain in its previous
* state, until you call 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;
@ -120,24 +128,41 @@ void led_set(uint8_t lednum, uint16_t red, uint16_t green, uint16_t blue)
}
/*
* Write the data stored in the LED buffers via led_set().
*/
void led_flush(void)
{
led1642gw_flush();
}
/*
* Clear the LED buffer.
* This function only affects the LED buffer, but not the LEDs, until
* you call led_flush().
*/
void led_clear(void)
{
led1642gw_clear();
}
/*
* 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();