/* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * 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 #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[3]; /* * 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_LE_L(); for (bit=15; bit>=le_clocks; bit--) { SET_CLK_L(); if(data&mask) { SET_SDI_H(); } else { SET_SDI_L(); } SET_CLK_H(); mask >>= 1; } SET_LE_H(); for (/*noting to initialize*/; bit>=0; bit--) { SET_CLK_L(); if(data&mask) { SET_SDI_H(); } else { SET_SDI_L(); } SET_CLK_H(); mask >>= 1; } // 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(void) { 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); } /* * 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<