185 lines
5.7 KiB
C
185 lines
5.7 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "esp_log.h"
|
|
#include "driver/uart.h"
|
|
#include "driver/rmt_tx.h"
|
|
#include "led_strip_encoder.h"
|
|
|
|
#define RMT_LED_STRIP_RESOLUTION_HZ 10000000
|
|
#define LED_GPIO_NUM 6
|
|
#define LED_NUMBERS 30
|
|
|
|
static const char *TAG = "led-laser";
|
|
|
|
static uint8_t led_pixels[LED_NUMBERS * 3];
|
|
static rmt_channel_handle_t led_chan = NULL;
|
|
static rmt_encoder_handle_t led_encoder = NULL;
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
int freq_hz;
|
|
int duration_min;
|
|
uint32_t hue;
|
|
} preset_t;
|
|
|
|
static const preset_t presets[] = {
|
|
{"Regeneration", 40, 60, 0},
|
|
{"Durchblutung", 60, 60, 15},
|
|
{"Tiefenwirkung",80,45, 5},
|
|
{"Gepulst Rot", 50, 60, 0},
|
|
{"Oberflächenlicht",30,45,20},
|
|
{"Muskeln/Gelenke",65,60,10},
|
|
{"Ganzkörper", 45, 90, 0}
|
|
};
|
|
#define PRESET_COUNT (sizeof(presets)/sizeof(presets[0]))
|
|
|
|
static int current_preset = -1;
|
|
static bool led_on = false;
|
|
static uint64_t last_toggle_ms = 0;
|
|
|
|
static void hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b) {
|
|
h %= 360;
|
|
uint32_t rgb_max = v * 255 / 100;
|
|
uint32_t rgb_min = rgb_max * (100 - s) / 100;
|
|
uint32_t i = h / 60;
|
|
uint32_t diff = h % 60;
|
|
uint32_t adj = (rgb_max - rgb_min) * diff / 60;
|
|
switch(i){
|
|
case 0: *r=rgb_max; *g=rgb_min+adj; *b=rgb_min; break;
|
|
case 1: *r=rgb_max-adj; *g=rgb_max; *b=rgb_min; break;
|
|
case 2: *r=rgb_min; *g=rgb_max; *b=rgb_min+adj; break;
|
|
case 3: *r=rgb_min; *g=rgb_max-adj; *b=rgb_max; break;
|
|
case 4: *r=rgb_min+adj; *g=rgb_min; *b=rgb_max; break;
|
|
default:*r=rgb_max; *g=rgb_min; *b=rgb_max-adj; break;
|
|
}
|
|
}
|
|
|
|
static void set_all_pixels(uint32_t r, uint32_t g, uint32_t b) {
|
|
for(int i=0;i<LED_NUMBERS;i++){
|
|
led_pixels[i*3+0]= (uint8_t)g;
|
|
led_pixels[i*3+1]= (uint8_t)b;
|
|
led_pixels[i*3+2]= (uint8_t)r;
|
|
}
|
|
}
|
|
|
|
static void flush_leds(void){
|
|
rmt_transmit_config_t tx_cfg = { .loop_count = 0 };
|
|
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_pixels, sizeof(led_pixels), &tx_cfg));
|
|
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
|
|
}
|
|
|
|
static void apply_preset(int idx){
|
|
if(idx<0 || idx>=PRESET_COUNT) return;
|
|
current_preset = idx;
|
|
const preset_t *p = &presets[idx];
|
|
uint32_t r,g,b;
|
|
hsv2rgb(p->hue, 100, 100, &r,&g,&b);
|
|
set_all_pixels(r,g,b);
|
|
led_on = true;
|
|
last_toggle_ms = esp_timer_get_time()/1000;
|
|
ESP_LOGI(TAG, "Preset %d %s %dHz", idx, p->name, p->freq_hz);
|
|
}
|
|
|
|
static void stop_leds(void){
|
|
current_preset = -1;
|
|
memset(led_pixels,0,sizeof(led_pixels));
|
|
flush_leds();
|
|
ESP_LOGI(TAG,"LEDs stopped");
|
|
}
|
|
|
|
static void list_presets(void){
|
|
printf("\n--- Presets ---\n");
|
|
for(int i=0;i<PRESET_COUNT;i++){
|
|
const preset_t *p=&presets[i];
|
|
printf("%d - %s %dHz %dmin\n", i, p->name, p->freq_hz, p->duration_min);
|
|
}
|
|
printf("Commands: 0-6 select, next, stop, list\n");
|
|
}
|
|
|
|
static void process_line(char *line){
|
|
if(strcmp(line,"stop")==0){ stop_leds(); return; }
|
|
if(strcmp(line,"next")==0){
|
|
int nxt = (current_preset+1)%PRESET_COUNT;
|
|
apply_preset(nxt);
|
|
return;
|
|
}
|
|
if(strcmp(line,"list")==0){ list_presets(); return; }
|
|
if(strlen(line)==1 && line[0]>='0' && line[0]<='6'){
|
|
int idx = line[0]-'0';
|
|
if(idx<PRESET_COUNT){ apply_preset(idx); return; }
|
|
}
|
|
printf("Unknown: %s\n", line);
|
|
}
|
|
|
|
void app_main(void){
|
|
ESP_LOGI(TAG,"LED Laser Frequenz start");
|
|
|
|
uart_config_t uart_cfg = {
|
|
.baud_rate = 115200,
|
|
.data_bits = UART_DATA_8_BITS,
|
|
.parity = UART_PARITY_DISABLE,
|
|
.stop_bits = UART_STOP_BITS_1,
|
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
|
|
};
|
|
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_0, 1024,0,0,NULL,0));
|
|
ESP_ERROR_CHECK(uart_param_config(UART_NUM_0,&uart_cfg));
|
|
|
|
rmt_tx_channel_config_t tx_cfg = {
|
|
.clk_src = RMT_CLK_SRC_DEFAULT,
|
|
.gpio_num = LED_GPIO_NUM,
|
|
.mem_block_symbols = 64,
|
|
.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ,
|
|
.trans_queue_depth = 4
|
|
};
|
|
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_cfg,&led_chan));
|
|
led_strip_encoder_config_t enc_cfg = { .resolution = RMT_LED_STRIP_RESOLUTION_HZ };
|
|
ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&enc_cfg,&led_encoder));
|
|
ESP_ERROR_CHECK(rmt_enable(led_chan));
|
|
|
|
memset(led_pixels,0,sizeof(led_pixels));
|
|
flush_leds();
|
|
|
|
char line_buf[64];
|
|
int line_pos=0;
|
|
|
|
while(1){
|
|
int ch;
|
|
while(uart_get_buffered_data_len(UART_NUM_0) > 0){
|
|
uint8_t c;
|
|
int len = uart_read_bytes(UART_NUM_0,&c,1,0);
|
|
if(len>0){
|
|
if(c=='\r' || c=='\n'){
|
|
line_buf[line_pos]='\0';
|
|
if(line_pos>0){ process_line(line_buf); }
|
|
line_pos=0;
|
|
}else{
|
|
if(line_pos < (int)sizeof(line_buf)-1){ line_buf[line_pos++]=c; }
|
|
}
|
|
}
|
|
}
|
|
|
|
if(current_preset>=0){
|
|
const preset_t *p=&presets[current_preset];
|
|
uint64_t now = esp_timer_get_time()/1000;
|
|
uint64_t period_ms = 1000 / p->freq_hz;
|
|
uint64_t half = period_ms/2;
|
|
if(half<1) half=1;
|
|
if(now - last_toggle_ms >= half){
|
|
led_on = !led_on;
|
|
last_toggle_ms = now;
|
|
if(led_on){
|
|
uint32_t r,g,b;
|
|
hsv2rgb(p->hue,100,100,&r,&g,&b);
|
|
set_all_pixels(r,g,b);
|
|
}else{
|
|
memset(led_pixels,0,sizeof(led_pixels));
|
|
}
|
|
flush_leds();
|
|
}
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
}
|
|
}
|