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