163 lines
4.8 KiB
C
163 lines
4.8 KiB
C
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#include "pico/stdlib.h"
|
||
|
|
#include "hardware/pio.h"
|
||
|
|
#include "hardware/clocks.h"
|
||
|
|
#include "ws2812.pio.h"
|
||
|
|
#include "ch9120.h"
|
||
|
|
|
||
|
|
#define WS2812_PIN 25
|
||
|
|
#define LED_FREQ 800000
|
||
|
|
|
||
|
|
void put_pixel(uint32_t pixel_grb) {
|
||
|
|
pio_sm_put_blocking(pio0, 0, pixel_grb << 8u);
|
||
|
|
}
|
||
|
|
|
||
|
|
void put_rgb(uint8_t red, uint8_t green, uint8_t blue) {
|
||
|
|
uint32_t mask = (green << 16) | (red << 8) | (blue << 0);
|
||
|
|
put_pixel(mask);
|
||
|
|
}
|
||
|
|
|
||
|
|
void parse_color_command(const char *cmd, uint8_t *r, uint8_t *g, uint8_t *b) {
|
||
|
|
if (strncmp(cmd, "RGB:", 4) == 0) {
|
||
|
|
sscanf(cmd + 4, "%hhu,%hhu,%hhu", r, g, b);
|
||
|
|
} else if (strcmp(cmd, "RED") == 0) {
|
||
|
|
*r = 255; *g = 0; *b = 0;
|
||
|
|
} else if (strcmp(cmd, "GREEN") == 0) {
|
||
|
|
*r = 0; *g = 255; *b = 0;
|
||
|
|
} else if (strcmp(cmd, "BLUE") == 0) {
|
||
|
|
*r = 0; *g = 0; *b = 255;
|
||
|
|
} else if (strcmp(cmd, "WHITE") == 0) {
|
||
|
|
*r = 255; *g = 255; *b = 255;
|
||
|
|
} else if (strcmp(cmd, "OFF") == 0) {
|
||
|
|
*r = 0; *g = 0; *b = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
stdio_init_all();
|
||
|
|
|
||
|
|
printf("RP2040-ETH WS2812 Network Control\n");
|
||
|
|
|
||
|
|
// Initialize WS2812 LED
|
||
|
|
PIO pio = pio0;
|
||
|
|
int sm = 0;
|
||
|
|
uint offset = pio_add_program(pio, &ws2812_program);
|
||
|
|
ws2812_program_init(pio, sm, offset, WS2812_PIN, LED_FREQ, true);
|
||
|
|
|
||
|
|
// Initialize CH9120 Ethernet
|
||
|
|
CH9120_init();
|
||
|
|
printf("Ethernet initialized\n");
|
||
|
|
printf("IP: 192.168.1.201\n");
|
||
|
|
printf("Port: 1000\n");
|
||
|
|
printf("Mode: TCP Server\n");
|
||
|
|
printf("Send color commands: RED, GREEN, BLUE, WHITE, OFF, or RGB:r,g,b\n");
|
||
|
|
|
||
|
|
// Flash LED to indicate startup
|
||
|
|
for (int i = 0; i < 3; i++) {
|
||
|
|
put_rgb(0, 0, 255); // Blue flash
|
||
|
|
sleep_ms(200);
|
||
|
|
put_rgb(0, 0, 0); // Off
|
||
|
|
sleep_ms(200);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Current LED state
|
||
|
|
uint8_t current_r = 0, current_g = 0, current_b = 0;
|
||
|
|
uint8_t target_r = 0, target_g = 0, target_b = 0;
|
||
|
|
bool color_changing = false;
|
||
|
|
|
||
|
|
char rx_buffer[256];
|
||
|
|
uint32_t last_heartbeat = 0;
|
||
|
|
uint32_t last_blink = 0;
|
||
|
|
bool show_blink = false;
|
||
|
|
|
||
|
|
while (1) {
|
||
|
|
// Check for network data
|
||
|
|
int received = CH9120_receive_data(rx_buffer, sizeof(rx_buffer) - 1);
|
||
|
|
if (received > 0) {
|
||
|
|
rx_buffer[received] = '\0';
|
||
|
|
|
||
|
|
// Flash amber to indicate traffic
|
||
|
|
put_rgb(255, 191, 0); // Amber
|
||
|
|
sleep_ms(50);
|
||
|
|
|
||
|
|
// Parse color command
|
||
|
|
uint8_t new_r, new_g, new_b;
|
||
|
|
parse_color_command(rx_buffer, &new_r, &new_g, &new_b);
|
||
|
|
|
||
|
|
// Set new target color
|
||
|
|
target_r = new_r;
|
||
|
|
target_g = new_g;
|
||
|
|
target_b = new_b;
|
||
|
|
color_changing = true;
|
||
|
|
|
||
|
|
// Send acknowledgment
|
||
|
|
char ack[64];
|
||
|
|
snprintf(ack, sizeof(ack), "Setting color to R:%d G:%d B:%d\n", new_r, new_g, new_b);
|
||
|
|
CH9120_send_data(ack, strlen(ack));
|
||
|
|
|
||
|
|
// Flash amber again for outgoing traffic
|
||
|
|
put_rgb(255, 191, 0); // Amber
|
||
|
|
sleep_ms(50);
|
||
|
|
|
||
|
|
printf("Received command: %s\n", rx_buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Smooth color transition
|
||
|
|
if (color_changing) {
|
||
|
|
bool done = true;
|
||
|
|
|
||
|
|
if (current_r != target_r) {
|
||
|
|
current_r += (current_r < target_r) ? 1 : -1;
|
||
|
|
done = false;
|
||
|
|
}
|
||
|
|
if (current_g != target_g) {
|
||
|
|
current_g += (current_g < target_g) ? 1 : -1;
|
||
|
|
done = false;
|
||
|
|
}
|
||
|
|
if (current_b != target_b) {
|
||
|
|
current_b += (current_b < target_b) ? 1 : -1;
|
||
|
|
done = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
put_rgb(current_r, current_g, current_b);
|
||
|
|
|
||
|
|
if (done) {
|
||
|
|
color_changing = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
sleep_ms(3);
|
||
|
|
} else {
|
||
|
|
// Keep current color
|
||
|
|
put_rgb(current_r, current_g, current_b);
|
||
|
|
sleep_ms(10);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Periodic green flash to show firmware is running (regardless of state)
|
||
|
|
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||
|
|
|
||
|
|
// Check if it's time to blink (every 1 second)
|
||
|
|
if (now - last_blink >= 1000) {
|
||
|
|
show_blink = true;
|
||
|
|
last_blink = now;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Show green flash for 100ms
|
||
|
|
if (show_blink && (now - last_blink < 100)) {
|
||
|
|
put_rgb(0, 128, 0); // 50% green
|
||
|
|
}
|
||
|
|
|
||
|
|
// Clear blink flag after 100ms
|
||
|
|
if (now - last_blink >= 100) {
|
||
|
|
show_blink = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Heartbeat log every 5 seconds
|
||
|
|
if (now - last_heartbeat > 5000) {
|
||
|
|
printf("Ethernet heartbeat - waiting for commands...\n");
|
||
|
|
last_heartbeat = now;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|