blob: 6db54d53f5bc70f81ef2eebd8b249837f29236a5 [file] [log] [blame]
#include "frc971/wpilib/LPD8806.h"
#include "frc971/queues/gyro.q.h"
#include "frc971/wpilib/ahal/SPI.h"
#undef ERROR
namespace frc971 {
namespace wpilib {
LPD8806::LPD8806(int chips)
: chips_(chips),
data_(new LED[chips * 2]),
spi_(new frc::SPI(frc::SPI::kOnboardCS1)) {
memset(data_.get(), 0, sizeof(LED[chips_ * 2]));
// 2 MHz is the maximum frequency the datasheet recommends.
spi_->SetClockRate(2e6);
spi_->SetChipSelectActiveHigh();
// Clock is inverted due to the level translator chip.
spi_->SetClockActiveLow();
spi_->SetSampleDataOnRising();
spi_->SetMSBFirst();
}
void LPD8806::SetColor(int led, uint32_t hex_color) {
CHECK_LT(led, chips_ * 2);
::aos::MutexLocker locker(&data_mutex_);
data_[led].red = TranslateColor(hex_color, RED);
data_[led].green = TranslateColor(hex_color, GREEN);
data_[led].blue = TranslateColor(hex_color, BLUE);
}
uint8_t LPD8806::TranslateColor(uint32_t hex_color, Type type) {
switch (type) {
case RED:
return ((hex_color >> 16) & 0xFF) | 0x01;
case GREEN:
return ((hex_color >> 8) & 0xFF) | 0x01;
case BLUE:
return (hex_color & 0xFF) | 0x01;
}
LOG(FATAL, "Not sure what color type %d is\n", static_cast<int>(type));
}
void LPD8806::operator()() {
// The buffer we're going to send.
// With 64 leds, it takes about 1ms to send them all, which fits within the
// 5ms cycle used by the gyro_reader.
LED buffer[64];
while (run_) {
if (next_led_to_send_ < chips_ * 2) {
::aos::MutexLocker locker(&data_mutex_);
memcpy(buffer, &data_[next_led_to_send_], sizeof(buffer));
next_led_to_send_ += 64;
} else {
CHECK_EQ(chips_ * 2, next_led_to_send_);
next_led_to_send_ = 0;
memset(buffer, 0, sizeof(buffer));
}
// Wait until right after the gyro gets a reading.
::frc971::sensors::gyro_reading.FetchNextBlocking();
int spi_send_result = (spi_->Write(
static_cast<uint8_t *>(static_cast<void *>(buffer)), sizeof(buffer)));
switch (spi_send_result) {
case -1:
LOG(INFO, "SPI::Write failed\n");
// Who knows what state it's in now, so start fresh next cycle.
next_led_to_send_ = chips_ * 2;
break;
case sizeof(buffer):
break;
default:
LOG(FATAL, "SPI::Write returned something weird: %d\n",
static_cast<int>(spi_send_result));
}
}
}
} // namespace wpilib
} // namespace frc971