#include "driver/ledc.h"
#include <SPI.h>
#define TLC5957_SDI_PIN 6 // Serial Data Input Pin
#define TLC5957_SCK_PIN 7 // Serial Clock Pin
#define TLC5957_XLAT_PIN 15 // Latch Pin
#define TLC5957_GSCLK_PIN 16 // Greyscale Clock Pin
#define ROTOR_A_PIN 17
#define ROTOR_B_PIN 18
#define EDGES_WRTGS 1
#define EDGES_LATGS 3
#define CLK_MICROS 20
#define DELAY_MICROS 100000
#define SPI_MISO 8
#define SPI_MOSI 3
#define SPI_SCLK 46
#define SPI_SS 9
static const int spiClk = 30e6; // 20 MHz SPI clock
//uninitalised pointers to SPI objects
SPIClass * spi = NULL;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32-S3!");
setup_tlc5957();
spi = new SPIClass(FSPI);
spi->begin(SPI_SCLK, SPI_MISO, SPI_MOSI, SPI_SS); //SCLK, MISO, MOSI, SS
pinMode(spi->pinSS(), OUTPUT); //VSPI SS
digitalWrite(spi->pinSS(), HIGH); //pull SS slow to prep other end for transfer
delay(100);
};
void setup_tlc5957() {
setup_gsclk();
pinMode(TLC5957_SDI_PIN, OUTPUT);
pinMode(TLC5957_SCK_PIN, OUTPUT);
pinMode(TLC5957_XLAT_PIN, OUTPUT);
pinMode(ROTOR_A_PIN, OUTPUT);
pinMode(ROTOR_B_PIN, OUTPUT);
}
void setup_gsclk() {
ledc_timer_config_t timer_config;
timer_config.speed_mode = LEDC_LOW_SPEED_MODE; // timer mode
timer_config.duty_resolution = LEDC_TIMER_1_BIT; // resolution of PWM duty, e.g. LEDC_TIMER_10_BIT
timer_config.timer_num = LEDC_TIMER_3; // timer index
timer_config.freq_hz = 20e6; // 20 MHz frequency of PWM signal
timer_config.clk_cfg = LEDC_USE_APB_CLK;
ledc_channel_config_t channel_config = {
.gpio_num = TLC5957_GSCLK_PIN,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_3,
.duty = 1,
.hpoint = 0
};
ledc_timer_config(&timer_config);
ledc_channel_config(&channel_config);
}
void spiCommand(SPIClass *spi, byte data) {
//use it as you would the regular arduino SPI API
spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end for transfer
spi->transfer(data);
spi->transfer(data);
spi->transfer(data);
spi->transfer(data);
spi->transfer(data);
spi->transfer(data);
digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end of data transfer
spi->endTransaction();
}
void loop() {
spiCommand(spi, 0b01010101); // junk data to illustrate usage
delay(100);
main();
}
// Function to send a byte of data serially to TLC5957
void sendByte(uint8_t byte)
{
for (int i = 7; i >= 0; i--)
{
digitalWrite(TLC5957_SDI_PIN, (byte >> i) & 0x01); // Send each bit serially
digitalWrite(TLC5957_SCK_PIN, 1); // Clock high
digitalWrite(TLC5957_SCK_PIN, 0); // Clock low
}
}
void activate_a() {
digitalWrite(ROTOR_B_PIN, 1);
digitalWrite(ROTOR_A_PIN, 0);
}
void activate_b() {
digitalWrite(ROTOR_A_PIN, 1);
digitalWrite(ROTOR_B_PIN, 0);
}
void WRTGS(uint16_t *data, uint8_t rising_edges)
{
sendByte(data[0] >> 8 & 0xff);
sendByte(data[0] & 0xff);
sendByte(data[1] >> 8 & 0xff);
sendByte(data[1] & 0xff);
sendByte(data[2] >> 8 & 0xff);
// turn on LAT on the last clk cycle for 1 cycle
uint8_t byte = data[2] & 0xff;
for (int i = 7; i >= 0; i--)
{
digitalWrite(TLC5957_SDI_PIN, (byte >> i) & 0x01); // Send each bit serially
digitalWrite(TLC5957_SCK_PIN, 1); // Clock high
digitalWrite(TLC5957_SCK_PIN, 0); // Clock low
if (i == rising_edges)
{
digitalWrite(TLC5957_XLAT_PIN, 1);
}
if (i == 0)
{
digitalWrite(TLC5957_XLAT_PIN, 0);
}
}
}
void LATGS(uint16_t *data)
{
for (int i = 0; i < 15; i++)
{
WRTGS(data + i * 3, EDGES_WRTGS);
}
WRTGS(data + 3 * 15, EDGES_LATGS);
}
int main()
{
uint16_t tlcData4[48]; // = {0x0000, 0x0000, 0x0000};
// int counter = 0;
// while (1)
// {
// printf("\r%d", counter++);
// fflush(stdout);
// for (int i = 0; i < 48; i++)
// {
// uint16_t tmp = (((float)i) / 47.0f) * (float)0xffff;
// tlcData4[i] = linearToLogarithmic(tmp, 0xffff);
// printf("%d=%d (was %d)\n", i, tlcData4[i], tmp);
// }
// #if 0
// for (int i = 0; i < 48; i++)
// {
// // tlcData4[i]=0;
// // if (i < 24) {
// uint16_t tmp = linearToLogarithmic((((float)i) / 48.0f) * (float)0xffff, (uint16_t)0xffff);
// printf("%d=%d (was %d)\n", i, tlcData4[i], tmp);
// tlcData4[i] = tmp;
// // }
// }
// #endif
// LATGS(tlcData4);
// exit(0);
// }
while (1)
{
// fill inside out
for (int pos = 0; pos < 48; pos++)
{
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0;
if (i < pos)
{
tlcData4[i] = 0x88;
}
}
LATGS(tlcData4);
if (pos%2 == 0)
activate_a();
else
activate_b();
usleep(DELAY_MICROS);
}
// clear inside to outside
for (int pos = 0; pos < 48; pos++)
{
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0;
if (i > pos)
{
tlcData4[i] = 0x88;
}
}
LATGS(tlcData4);
if (pos%2 == 0)
activate_a();
else
activate_b();
usleep(DELAY_MICROS);
}
// ping pong
for (int pos = 0; pos < 48; pos++)
{
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0;
if (pos == i)
{
tlcData4[i] = 0xff;
}
}
LATGS(tlcData4);
if (pos%2 == 0)
activate_a();
else
activate_b();
usleep(DELAY_MICROS);
}
// ping pong
for (int pos = 48; pos > 0; pos--)
{
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0;
if (pos == i)
{
tlcData4[i] = 0x88;
}
}
LATGS(tlcData4);
if (pos%2 == 0)
activate_a();
else
activate_b();
usleep(DELAY_MICROS);
}
// full flash a
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0xaa;
}
activate_a();
LATGS(tlcData4);
usleep(48*15e3);
// full flash b
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0xaa;
}
activate_b();
LATGS(tlcData4);
usleep(48*15e3);
// full off
for (int i = 0; i < 48; i++)
{
tlcData4[i] = 0x00;
}
LATGS(tlcData4);
usleep(48*15e3);
}
return 0;
}