blob: 6f6304f421e854e4a01eb5ed3f464d68b7fc83d2 [file] [log] [blame]
Comran Morshed33ad1692015-12-06 18:53:02 +00001#include "frc971/wpilib/LPD8806.h"
2
3#include "frc971/queues/gyro.q.h"
4
5#include "SPI.h"
6
7namespace frc971 {
8namespace wpilib {
9
10LPD8806::LPD8806(int chips)
11 : chips_(chips),
12 data_(new LED[chips * 2]),
13 spi_(new SPI(SPI::kOnboardCS1)) {
14 memset(data_.get(), 0, sizeof(LED[chips_ * 2]));
15
16 // 2 MHz is the maximum frequency the datasheet recommends.
17 spi_->SetClockRate(2e6);
18 spi_->SetChipSelectActiveHigh();
19
20 // Clock is inverted due to the level translator chip.
21 spi_->SetClockActiveLow();
22 spi_->SetSampleDataOnRising();
23 spi_->SetMSBFirst();
24}
25
26void LPD8806::SetColor(int led, uint32_t hex_color) {
27 CHECK_LT(led, chips_ * 2);
28 ::aos::MutexLocker locker(&data_mutex_);
29 data_[led].red = TranslateColor(hex_color, RED);
30 data_[led].green = TranslateColor(hex_color, GREEN);
31 data_[led].blue = TranslateColor(hex_color, BLUE);
32}
33
34uint8_t LPD8806::TranslateColor(uint32_t hex_color, Type type) {
35 switch (type) {
36 case RED:
37 return ((hex_color >> 16) & 0xFF) | 0x01;
38 case GREEN:
39 return ((hex_color >> 8) & 0xFF) | 0x01;
40 case BLUE:
41 return (hex_color & 0xFF) | 0x01;
42 }
43
44 LOG(FATAL, "Not sure what color type %d is\n", static_cast<int>(type));
45}
46
47void LPD8806::operator()() {
48 // The buffer we're going to send.
49 // With 64 leds, it takes about 1ms to send them all, which fits within the
50 // 5ms cycle used by the gyro_reader.
51 LED buffer[64];
52
53 while (run_) {
54 if (next_led_to_send_ < chips_ * 2) {
55 ::aos::MutexLocker locker(&data_mutex_);
56 memcpy(buffer, &data_[next_led_to_send_], sizeof(buffer));
57 next_led_to_send_ += 64;
58 } else {
59 CHECK_EQ(chips_ * 2, next_led_to_send_);
60 next_led_to_send_ = 0;
61 memset(buffer, 0, sizeof(buffer));
62 }
63
64 // Wait until right after the gyro gets a reading.
65 ::frc971::sensors::gyro_reading.FetchNextBlocking();
66
67 int spi_send_result = (spi_->Write(
68 static_cast<uint8_t *>(static_cast<void *>(buffer)), sizeof(buffer)));
69
70 switch (spi_send_result) {
71 case -1:
72 LOG(INFO, "SPI::Write failed\n");
73 // Who knows what state it's in now, so start fresh next cycle.
74 next_led_to_send_ = chips_ * 2;
75 break;
76 case sizeof(buffer):
77 break;
78 default:
79 LOG(FATAL, "SPI::Write returned something weird: %d\n",
80 static_cast<int>(spi_send_result));
81 }
82 }
83}
84
85} // namespace wpilib
86} // namespace frc971