logicanalyzer
24 channel, 100Msps logic analyzer hardware and software
#include "LogicAnalyzer_Board_Settings.h"
#ifdef WS2812B_LED
/* Libraries */
#include "pico/stdlib.h"
#include "LogicAnalyzer_W2812B.h"
/* For WS2812B */
/* Datasheet used: https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf */
/* WARNING: Due to WS2812B being 5V logic and the RP2040 being 3v3 a level shifter is needed */
/* You will not fry the pins or anything if you accidentally hook it up, it just won't register */
/* This is because WS2812B registers 0.7VDD as a minimum for logic high, 0.7*5V => 3.5V which is above what the RP2040 can do */
/* Assembler functions */
/* If you place this in a .cpp file make sure to change /extern/ to /extern "C"/ */
/* eg; extern "C" void function(); */
extern void cycle_delay_t0h();
extern void cycle_delay_t0l();
extern void cycle_delay_t1h();
extern void cycle_delay_t1l();
extern uint32_t disable_and_save_interrupts(); /* Used for interrupt disabling */
extern void enable_and_restore_interrupts(uint32_t); /* Used for interrupt enabling */
/* The GPIO pin for the LED data */
#define LED_PIN LED_IO
/* Number of individual LEDs */
/* You can have up to 80,000 LEDs before you run out of memory */
#define LED_NUM 1
/* Leave alone, only defined to hammer it into the compilers head */
#define LED_DATA_SIZE 3
#define LED_BYTE_SIZE LED_NUM * LED_DATA_SIZE
/* We are not here to waste any memory, 3 bytes per LED */
uint8_t led_data[LED_BYTE_SIZE];
/* Sets a specific LED to a certain color */
/* LEDs start at 0 */
void set_led(uint32_t led, uint8_t r, uint8_t g, uint8_t b)
{
led_data[led * LED_DATA_SIZE] = g; /* Green */
led_data[(led * LED_DATA_SIZE) + 1] = r; /* Red */
led_data[(led * LED_DATA_SIZE) + 2] = b; /* Blue */
}
/* Sets all the LEDs to a certain color */
void set_all(uint8_t r, uint8_t g, uint8_t b)
{
for (uint32_t i = 0; i < LED_BYTE_SIZE; i += LED_DATA_SIZE)
{
led_data[i] = g; /* Green */
led_data[i + 1] = r; /* Red */
led_data[i + 2] = b; /* Blue */
}
}
/* Sends the data to the LEDs */
void send_led_data()
{
/* Disable all interrupts and save the mask */
uint32_t interrupt_mask = disable_and_save_interrupts();
/* Get the pin bit */
uint32_t pin = 1UL << LED_PIN;
/* Declared outside to force optimization if compiler gets any funny ideas */
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
uint32_t i = 0;
int8_t j = 0;
for (i = 0; i < LED_BYTE_SIZE; i += LED_DATA_SIZE)
{
/* Send order is green, red, blue because someone messed up big time */
/* Look up values once, a micro optimization, assume compiler is dumb as a brick */
green = led_data[i];
red = led_data[i + 1];
blue = led_data[i + 2];
for (j = 7; j >= 0; j--) /* Handle the 8 green bits */
{
/* Get Nth bit */
if (((green >> j) & 1) == 1) /* The bit is 1 */
{
sio_hw->gpio_set = pin; /* This sets the specific pin to high */
cycle_delay_t1h(); /* Delay by datasheet amount (800ns give or take) */
sio_hw->gpio_clr = pin; /* This sets the specific pin to low */
cycle_delay_t1l(); /* Delay by datasheet amount (450ns give or take) */
}
else /* The bit is 0 */
{
sio_hw->gpio_set = pin;
cycle_delay_t0h();
sio_hw->gpio_clr = pin;
cycle_delay_t0l();
}
}
for (j = 7; j >= 0; j--) /* Handle the 8 red bits */
{
if (((red >> j) & 1) == 1)
{
sio_hw->gpio_set = pin;
cycle_delay_t1h();
sio_hw->gpio_clr = pin;
cycle_delay_t1l();
}
else
{
sio_hw->gpio_set = pin;
cycle_delay_t0h();
sio_hw->gpio_clr = pin;
cycle_delay_t0l();
}
}
for (j = 7; j >= 0; j--) /* Handle the 8 blue bits */
{
if (((blue >> j) & 1) == 1)
{
sio_hw->gpio_set = pin;
cycle_delay_t1h();
sio_hw->gpio_clr = pin;
cycle_delay_t1l();
}
else
{
sio_hw->gpio_set = pin;
cycle_delay_t0h();
sio_hw->gpio_clr = pin;
cycle_delay_t0l();
}
}
}
/* Set the level low to indicate a reset is happening */
sio_hw->gpio_clr = pin;
/* Enable the interrupts that got disabled */
enable_and_restore_interrupts(interrupt_mask);
/* Make sure to wait any amount of time after you call this function */
}
void init_led(void)
{
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_put(LED_PIN, false); /* Important to start low to tell the LEDs that it's time for new data */
sleep_ms(10);
}
void led_on(void)
{
set_led(0, 200,200,200);
send_led_data();
sleep_ms(10);
}
void led_off(void)
{
set_led(0, 0,0,0);
send_led_data();
sleep_ms(10);
}
void led_set(uint8_t r, uint8_t g, uint8_t b)
{
set_led(0, r, g, b);
send_led_data();
}
// int main()
// {
// /* System init */
// gpio_init(LED_PIN);
// gpio_set_dir(LED_PIN, GPIO_OUT);
// gpio_put(LED_PIN, false); /* Important to start low to tell the LEDs that it's time for new data */
// /* 100MHz is a clean number and used to calculate the cycle delays */
// set_sys_clock_khz(100000, true);
// /* Wait a bit to ensure clock is running and force LEDs to reset*/
// sleep_ms(10);
// /* Used for example */
// int32_t led = 0;
// uint8_t led_dir = 1;
// uint8_t dim_value = 1;
// uint8_t dim_dir = 1;
// uint32_t timer = 2; /* Change LEDs every 2ms, basically a speed control, higher is slower */
// uint32_t timer_val = 0; /* Track current time */
// while (true)
// {
// /* Go crazy */
// /* Only need to update LEDs once every 2ms */
// if (timer_val > timer)
// {
// /*-- I'm using this to dim the LEDs on and off with the color white --*/
// if (dim_value >= 26) /* Start dimming down */
// {
// dim_value = 25;
// dim_dir = 0;
// }
// else if(dim_value == 0) /* Start dimming up */
// {
// dim_dir = 1;
// }
// if (dim_dir)
// dim_value++;
// else
// dim_value--;
// /* Set LED data to dimmed white */
// set_all(dim_value, dim_value, dim_value);
// /*---------------------------------------------------------------------*/
// /*-- I'm using this to race a red LED back and forth across the strip --*/
// if (led < 0) /* Reached end, go back */
// {
// led = 0;
// led_dir = 1;
// }
// else if(led >= LED_NUM - 1) /* Reached other end, go back */
// {
// led = LED_NUM - 1;
// led_dir = 0;
// }
// /* Set new position */
// set_led(led, 100, 0, 0); /* Red */
// /* Move LED for next iteration */
// if (led_dir)
// led++;
// else
// led--;
// /*-----------------------------------------------------------------------*/
// timer_val = 0; /* Reset update cycle */
// }
// /* Send out the color data to the LEDs */
// send_led_data();
// /* Refresh rate for LEDs*/
// /* It is hard to estimate due to the logic above consuming time, but forcing it at 1ms + roughly 2.5ms from LED data transfer + 0.5ms logic above => 4ms per loop */
// /* Which is roughly 250Hz, but again this is a hard guess, it's probably even less */
// /* Also note that this is different from the update rate which is how fast you are updating your LED colors in code */
// sleep_ms(1);
// timer_val++;
// /* A wait is important like the sleep_ms() above. This is to give the LEDs a notice of reset. It expects anything more than 50us */
// }
// return 0;
// }
#endif