Skip to content

Instantly share code, notes, and snippets.

@bkrepo
Created October 13, 2016 09:10
Show Gist options
  • Select an option

  • Save bkrepo/bb23045dceec98a866e80cfe54baa01e to your computer and use it in GitHub Desktop.

Select an option

Save bkrepo/bb23045dceec98a866e80cfe54baa01e to your computer and use it in GitHub Desktop.
odlight: Ambilight for ODROID
/*----------------------------------------------------------------------------*/
/*
Ambilight Project : Arduino Uno Board with WS2801/WS2812B LED Strip
Arduino Pin Connection
- Mode 0 (1 wire) :
Data Out Pin 6
- Mode 1 (3 wire : spi mode = 0, clk = 2Mhz) :
Data Out Pin 11
Clock Out Pin 13
Connect to Board : H/W Serial (USB, ttyACM, Baud 1000000N81)
Dev Board : ODROID-C2
WS2812B Spec :
- Max Current : 60mA per 1 Cell (Max bright)
- Data Transfer : 800Khz Serial(1 wire) Communication(1.25us)
WS2801 Spec :
- Max Current : 120mA per 1 Cell (Max bright)
- Data Transfer : 2Mhz Serial(3 wire : spi mode) Communication
Use Library : Install Arduino Library folder
- Adafruit_NeoPixel : https://github.com/adafruit/Adafruit_NeoPixel
- Git clone : https://github.com/adafruit/Adafruit_NeoPixel.git
Protocol :
Receive : HEADER[4] + (num_of_leds in HEADER) * 3 bytes
Transceive : 'N' (Ack for Data received)
Header Information
'o', 'd', num of leds(1byte), check sum(1byte)
Check Sum Information
HEADER[3] = 0;
HEADER[3] ^= HEADER[0];
HEADER[3] ^= HEADER[1];
HEADER[3] ^= HEADER[2];
Serial Data send time : 10us/byte (Buad : 1000000 bps)
SPI Data send time : 5us/byte (SCKL : 2000000 Hz)
1 wire data send time : 12.5us/byte (Freq : 800000 Hz)
Hardkernel Co.,Ltd (2016/10/11)
*/
/*----------------------------------------------------------------------------*/
/* Include Adafruit NeoPixel library */
#include <Adafruit_NeoPixel.h>
#include <SPI.h>
/*----------------------------------------------------------------------------*/
/* Data Out PIN */
#define DOUT_PIN 6
#define MAX_LEDS 256
#define SERIAL_BAUD 1000000
#define HEADER_SIZE 4
/* Use LED type define */
#define LED_WS2801
#define LED_WS2812B
#define TIMEOUT_MSEC 1000
/*----------------------------------------------------------------------------*/
/* LED color data struct */
struct led_data_t {
uint8_t b;
uint8_t g;
uint8_t r;
};
/*----------------------------------------------------------------------------*/
/* Create 'leds' object to drive LEDs */
Adafruit_NeoPixel leds = Adafruit_NeoPixel(MAX_LEDS, DOUT_PIN, NEO_GRB + NEO_KHZ800);
/* Serial Data Receive buffer */
uint8_t SerialBuffer[sizeof(led_data_t) * MAX_LEDS];
/*----------------------------------------------------------------------------*/
void setup() {
/* H/W Serial Init */
Serial.begin(SERIAL_BAUD);
/* SPI Port Init for WS2801 LED, 80kbytes/sec */
SPI.setBitOrder(MSBFIRST);
/* SPI Clock = 16 Mhz / 8 = 2 Mhz, 200kbytes/sec */
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE0);
SPI.begin();
SPCR |= _BV(MSTR);
SPCR &= ~_BV(SPIE);
SPSR;
for(int i = 0; i < MAX_LEDS * sizeof(led_data_t); i++)
SPI.transfer(0x00);
/* NeoPixel Lib Init for WS2812B */
leds.begin();
leds.clear();
leds.show();
}
/*----------------------------------------------------------------------------*/
uint8_t check_timeout(unsigned long current_time)
{
static unsigned long prev_time;
unsigned long diff_time;
if (current_time) {
diff_time = current_time - prev_time;
if (diff_time > TIMEOUT_MSEC) {
prev_time = millis();
Serial.write("N");
return 1;
}
return 0;
}
prev_time = millis();
return 0;
}
/*----------------------------------------------------------------------------*/
uint16_t check_header() {
uint8_t header[4] = {0, };
uint16_t rx_cnt = 0;
/* start time check */
check_timeout(0);
while(true) {
if (Serial.available()) {
header[rx_cnt++] = Serial.read();
if (rx_cnt >= HEADER_SIZE) {
if ((header[0] == 'o') && (header[1] == 'd')) {
uint8_t check_sum = 0;
check_sum ^= header[0];
check_sum ^= header[1];
check_sum ^= header[2];
/* Return num of leds */
if (check_sum == header[3])
return (uint16_t)header[2];
}
rx_cnt -= 1;
header[0] = header[1];
header[1] = header[2];
header[2] = header[3];
}
}
else
check_timeout(millis());
}
}
/*----------------------------------------------------------------------------*/
void loop() {
uint16_t rx_cnt, recv_data_size;
while(true) {
timeout_data:
recv_data_size = check_header() * sizeof(led_data_t);
/* rx buffer pointer init */
rx_cnt = 0;
/* start time check */
check_timeout(0);
while(true) {
if (Serial.available())
SerialBuffer[rx_cnt++] = Serial.read();
else if (check_timeout(millis()))
goto timeout_data;
if (rx_cnt >= recv_data_size)
break;
}
#if defined(LED_WS2801)
/* WS2801 LED Update */
for (rx_cnt = 0; rx_cnt < recv_data_size; rx_cnt ++)
SPI.transfer(SerialBuffer[rx_cnt]);
#endif
#if defined(LED_WS2812B)
/* WS2812B LED Update */
recv_data_size /= sizeof(led_data_t);
led_data_t *led_data = (led_data_t *)&SerialBuffer[0];
for (rx_cnt = 0; rx_cnt < recv_data_size; rx_cnt++)
leds.setPixelColor(rx_cnt, leds.Color(led_data[rx_cnt].r,
led_data[rx_cnt].g,
led_data[rx_cnt].b));
leds.show();
#endif
/* Ack Send for Data Received */
Serial.print("N");
}
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment