This commit is contained in:
j3d1 2022-09-22 21:48:36 +02:00
parent ce8b71daf0
commit 9c5fb65a90
6 changed files with 390 additions and 30 deletions

View file

@ -25,14 +25,8 @@ steps:
commands: commands:
- apt update - apt update
- apt install -y make zip - apt install -y make zip
- cd pcb - make pcb -j$(nproc) BOARD=fiatlux
- kibot -d gen -c fiatlux.kiplot.yaml -s update_xml,run_drc -i - make pcb -j$(nproc) BOARD=fiatlux_cc48
- kibot -d gen -c fiatlux.kiplot.yaml -s update_xml,run_erc -i
- kibot -d gen -c fiatlux.kiplot.yaml -s run_drc,run_erc print_sch
- kibot -d gen -c fiatlux.kiplot.yaml -s all print_front gerbers
- ls -lA
- cd -
- make pcb -j$(nproc)
- name: case - name: case
image: debian:sid image: debian:sid
@ -67,7 +61,8 @@ steps:
files: files:
- firmware/firmware/fiatlux.bin - firmware/firmware/fiatlux.bin
- firmware/otaflash.py - firmware/otaflash.py
- pcb/pcb.zip - pcb/fiatlux_pcb.zip
- pcb/fiatlux_cc48_pcb.zip
checksum: checksum:
- sha512 - sha512
- md5 - md5

View file

@ -7,12 +7,12 @@
#include <espressif/esp_common.h> #include <espressif/esp_common.h>
constexpr unsigned syslog_buffer_size = 1024; constexpr unsigned syslog_buffer_size = 1024;
char syslog_buf[syslog_buffer_size]; char syslog_buf[syslog_buffer_size + 1];
volatile unsigned head = 0; volatile unsigned head = 0;
volatile unsigned streams = 0; volatile unsigned streams = 0;
extern "C" void syslog(const char *msg) { extern "C" void syslog(const char *msg) {
printf("syslog> %s", msg); //printf("syslog> %s", msg);
while (char c = *msg++) { while (char c = *msg++) {
syslog_buf[head++ % syslog_buffer_size] = c; syslog_buf[head++ % syslog_buffer_size] = c;
} }

View file

@ -9,24 +9,308 @@
#include <task.h> #include <task.h>
#include <esp/spi.h> #include <esp/spi.h>
#include <ws2812_i2s/ws2812_i2s.h>
const int signal_led_pin = 2; extern "C" {
#include <sysparam.h>
}
const int cs0 = 15; struct apa10xx_pixel_t {
const int gpio4 = 4; struct {
const int gpio5 = 5; unsigned int mod: 5, marker: 3;
} __attribute__((packed)) global = {0x1F, 0x7};
uint8_t b = 0;
uint8_t g = 0;
uint8_t r = 0;
};
static ws2812_pixel_t next_colour(int i) {
ws2812_pixel_t colour = {{0, 0, 0, 0}};
if(i == 8) {
colour.white = 32;
} else {
colour.red = i & 1 ? 32 : 0;
colour.green = i & 2 ? 32 : 0;
colour.blue = i & 4 ? 32 : 0;
}
return colour;
}
static apa10xx_pixel_t next_color(int i) {
apa10xx_pixel_t colour;
colour.global.mod = 8;
colour.r = i & 1 ? 32 : 0;
colour.g = i & 2 ? 32 : 0;
colour.b = i & 4 ? 32 : 0;
return colour;
}
rgba_t top_color;
rgba_t bottom_color;
namespace fiatlux {
struct hal_error_t {
constexpr hal_error_t() = default;
hal_error_t(const char *) {}
hal_error_t(const char *, hal_error_t *cause) {}
};
constexpr hal_error_t empty_error;
enum class hal_module_t {
NONE, SIGNAL, RELAIS, SPI_DIMMER, WS28X, APA10X
};
namespace ports {
hal_module_t spi = hal_module_t::NONE;
hal_module_t uart = hal_module_t::NONE;
hal_module_t gpio2 = hal_module_t::NONE;
hal_module_t gpio4 = hal_module_t::NONE;
hal_module_t gpio5 = hal_module_t::NONE;
hal_module_t gpio15 = hal_module_t::NONE;
}
namespace signal {
void write_data(bool data) {
gpio_write(2, !data);
}
void setup() {
gpio_enable(2, GPIO_OUTPUT);
}
}
namespace relais {
void write_data(bool a, bool b) {
gpio_write(4, a);
gpio_write(5, b);
}
void write_data(uint8_t data[2]) {
write_data((bool) data[0], (bool) data[1]);
}
void setup() {
gpio_enable(4, GPIO_OUTPUT);
gpio_enable(5, GPIO_OUTPUT);
}
}
namespace spi_dimmer {
constexpr int cs0 = 15;
void write_data(uint16_t data[6]) {
for (int i = 0; i < 6; ++i) {
int dac_val = (data[i] << 2) & 0x3FFC;
spi_transfer_8(1, ~(0x00));
gpio_write(cs0, true);
gpio_write(cs0, false);
spi_transfer_8(1, ~(0x01 << i));
gpio_write(cs0, true);
gpio_write(cs0, false);
spi_transfer_16(1, dac_val);
spi_transfer_8(1, ~(0x00));
gpio_write(cs0, true);
gpio_write(cs0, false);
spi_transfer_8(1, ~(0x01 << i));
gpio_write(cs0, true);
gpio_write(cs0, false);
}
}
void setup() {
gpio_enable(cs0, GPIO_OUTPUT);
spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, 1, SPI_BIG_ENDIAN, 1);
}
}
namespace ws28x {
void write_data(ws2812_pixel_t *data) {
ws2812_i2s_update(data, PIXEL_RGBW);
}
void setup(size_t len) {
ws2812_i2s_init(len, PIXEL_RGBW);
}
}
namespace apa10x {
void write_data(apa10xx_pixel_t *data, size_t len) {
spi_transfer_32(1, 0x00000000);
for (size_t i = 0; i < len; i++)
spi_transfer_32(1, *(uint32_t *) &data[i]);
//spi_transfer_32(1, *(uint32_t *) &data[len - 1]); // dunno maybe this helps
//spi_transfer_32(1, *(uint32_t *) &data[len - 1]); // dunno maybe this helps
spi_transfer_32(1, 0xFFFFFFFF);
spi_transfer_32(1, 0xFFFFFFFF);
}
void setup() {
spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, 1, SPI_LITTLE_ENDIAN, false);
}
}
hal_error_t write_channel(uint8_t *data, size_t count, size_t stride, hal_module_t mod) {
if(mod == hal_module_t::SIGNAL) {
if(count != 1)
return "unsupported value for count";
if(stride != 1)
return "unsupported value for stride";
signal::write_data(data[0]);
} else if(mod == hal_module_t::RELAIS) {
if(count != 2)
return "unsupported value for count";
if(stride != 1)
return "unsupported value for stride";
relais::write_data(data);
} else if(mod == hal_module_t::SPI_DIMMER) {
if(count != 6)
return "unsupported value for count";
if(stride != 2)
return "unsupported value for stride";
spi_dimmer::write_data((uint16_t *) data);
} else if(mod == hal_module_t::WS28X) {
if(stride != 4)
return "unsupported value for stride";
ws28x::write_data((ws2812_pixel_t *) data);
} else if(mod == hal_module_t::APA10X) {
if(stride != 4)
return "unsupported value for stride";
apa10x::write_data((apa10xx_pixel_t *) data, count);
} else {
return "unsupported module";
}
return empty_error;
}
hal_error_t setup_channel(size_t count, size_t stride, hal_module_t mod) {
/*if(mod == hal_module_t::SIGNAL) {
if(count != 1)
return "unsupported value for count";
if(stride != 1)
return "unsupported value for stride";
signal::write_data(data[0]);
} else if(mod == hal_module_t::RELAIS) {
if(count != 2)
return "unsupported value for count";
if(stride != 1)
return "unsupported value for stride";
relais::write_data(data);
} else if(mod == hal_module_t::SPI_DIMMER) {
if(count != 6)
return "unsupported value for count";
if(stride != 2)
return "unsupported value for stride";
spi_dimmer::write_data((uint16_t *) data);
} else if(mod == hal_module_t::WS28X) {
if(stride != 4)
return "unsupported value for stride";
ws28x::write_data((ws2812_pixel_t *) data, count);
} else if(mod == hal_module_t::APA10X) {
if(stride != 4)
return "unsupported value for stride";
apa10x::write_data((apa10xx_pixel_t *) data, count);
} else {
return "unsupported module";
}*/
return empty_error;
}
}
//ws2812_pixel_t **pixels_ptr;
extern "C" void signal_led(bool state) { extern "C" void signal_led(bool state) {
gpio_write(signal_led_pin, !state); fiatlux::signal::write_data(state);
} }
extern "C" void lux_task(void *pvParameters) {
gpio_enable(signal_led_pin, GPIO_OUTPUT); /* This task uses the high level GPIO API (esp_gpio.h) to blink an LED.
gpio_enable(cs0, GPIO_OUTPUT); *
gpio_enable(gpio4, GPIO_OUTPUT); */
gpio_enable(gpio5, GPIO_OUTPUT); extern "C" [[noreturn]] void lux_task(void *pvParameters) {
spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, 1, SPI_BIG_ENDIAN, 1);
vTaskDelete(nullptr); int32_t lux_ws2812_number = 240;
auto ret = sysparam_get_int32("lux_ws2812_number", &lux_ws2812_number);
if(ret != SYSPARAM_OK)
lux_ws2812_number = 240;
int32_t lux_apa10xx_number = 40;
ret = sysparam_get_int32("lux_apa10xx_number", &lux_apa10xx_number);
if(ret != SYSPARAM_OK)
lux_apa10xx_number = 40;
ws2812_pixel_t pixels[lux_ws2812_number];
ws2812_i2s_init(lux_ws2812_number, PIXEL_RGBW);
memset(pixels, 0, sizeof(ws2812_pixel_t) * lux_ws2812_number);
apa10xx_pixel_t leds[lux_apa10xx_number];
//lux_apa102c_number
//gpio_enable(9, GPIO_INPUT);
//gpio_enable(10, GPIO_INPUT);
//fiatlux::spi_dimmer::setup();
fiatlux::signal::setup();
fiatlux::relais::setup();
fiatlux::apa10x::setup();
while (true) {
/*for (int j = 0; j < 64; j++) {
for (int i = 0; i < 8; i++)
spi_dac(i, 64 * j);
//printf("> %d\n", 64*j);
vTaskDelay(100 / portTICK_PERIOD_MS);
}*/
/*gpio_write(gpio4, 1);
vTaskDelay(200 / portTICK_PERIOD_MS);
gpio_write(gpio4, 0);
for (int i = 0; i < 8; i++)
spi_dac(i, 0);
gpio_write(gpio5, 1);
vTaskDelay(200 / portTICK_PERIOD_MS);
gpio_write(gpio5, 0);*/
fiatlux::signal::write_data(false);
for (int c = 8; c >= 0; c--) {
/*for (auto &pixel: pixels) {
pixel = next_colour(c);
}*/
for (auto &led: leds) {
led = next_color(c);
}
for (int i = 0; i < 120; i++)
pixels[i] = {{top_color.r, top_color.g, top_color.b, top_color.a}};
for (int i = 120; i < 240; i++)
pixels[i] = {{bottom_color.r, bottom_color.g, bottom_color.b, bottom_color.a}};
ws2812_i2s_update(pixels, PIXEL_RGBW);
fiatlux::write_channel((uint8_t *) &leds[0], lux_apa10xx_number, 4, fiatlux::hal_module_t::APA10X);
vTaskDelay(200 / portTICK_PERIOD_MS);
}
fiatlux::relais::write_data(true, false);
vTaskDelay(200 / portTICK_PERIOD_MS);
fiatlux::relais::write_data(false, true);
vTaskDelay(200 / portTICK_PERIOD_MS);
fiatlux::relais::write_data(false, false);
fiatlux::signal::write_data(true);
vTaskDelay(200 / portTICK_PERIOD_MS);
}
} }

View file

@ -13,6 +13,16 @@ void lux_task(void *pvParameters);
void signal_led(bool state); void signal_led(bool state);
typedef struct {
char r;
char g;
char b;
char a;
} rgba_t;
extern rgba_t top_color;
extern rgba_t bottom_color;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -30,6 +30,8 @@ using namespace fiatlux;
#define vTaskDelayMs(ms) vTaskDelay((ms) / portTICK_PERIOD_MS) #define vTaskDelayMs(ms) vTaskDelay((ms) / portTICK_PERIOD_MS)
const char hex_lookup[] = "0123456789ABCDEF\0\0";
uint16_t voltage_val; uint16_t voltage_val;
struct { struct {
@ -230,6 +232,8 @@ void websocket_task(void *pvParameter) {
vTaskDelete(nullptr); vTaskDelete(nullptr);
} }
char str[] = "L00000000\n";
/** /**
* This function is called when websocket frame is received. * This function is called when websocket frame is received.
* *
@ -254,6 +258,47 @@ void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len,
// Clear Config // Clear Config
res.cmd = (messages::id) 'X'; res.cmd = (messages::id) 'X';
res.ret = OK; res.ret = OK;
} else if(data[0] == 'B') {
// Disable LED
uint32_t val = data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24);
bottom_color.r = data[7];
bottom_color.g = data[6];
bottom_color.b = data[5];
str[0] = 'B';
str[2] = hex_lookup[val & 0xF];
str[1] = hex_lookup[(val >> 4) & 0xF];
str[4] = hex_lookup[(val >> 8) & 0xF];
str[3] = hex_lookup[(val >> 12) & 0xF];
str[6] = hex_lookup[(val >> 16) & 0xF];
str[5] = hex_lookup[(val >> 20) & 0xF];
str[8] = hex_lookup[(val >> 24) & 0xF];
str[7] = hex_lookup[(val >> 28) & 0xF];
//
syslog(str);
//signal_led(false);
res.cmd = (messages::id) 'B';
res.ret = OK;
res.val = 1;
} else if(data[0] == 'T') {
// Disable LED
uint32_t val = data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24);
top_color.r = data[7];
top_color.g = data[6];
top_color.b = data[5];
str[0] = 'T';
str[2] = hex_lookup[val & 0xF];
str[1] = hex_lookup[(val >> 4) & 0xF];
str[4] = hex_lookup[(val >> 8) & 0xF];
str[3] = hex_lookup[(val >> 12) & 0xF];
str[6] = hex_lookup[(val >> 16) & 0xF];
str[5] = hex_lookup[(val >> 20) & 0xF];
str[8] = hex_lookup[(val >> 24) & 0xF];
str[7] = hex_lookup[(val >> 28) & 0xF];
syslog(str);
//signal_led(false);
res.cmd = (messages::id) 'T';
res.ret = OK;
res.val = 1;
} else if(data[0] == 'D') { } else if(data[0] == 'D') {
// Disable LED // Disable LED
syslog("G\n"); syslog("G\n");

View file

@ -259,9 +259,17 @@
</header> </header>
<footer> <footer>
<label> <label>
<input type="checkbox" name="onoffswitch" id="led-switch" onclick="gpio()"> <input type="checkbox" name="onoffswitch" id="led-switch" onclick="gpio(this.value)">
<span class="toggle button">toggle signal led</span> <span class="toggle button">toggle signal led</span>
</label> </label>
<label>
<span>toggle signal led</span>
<input type="color" onchange="colorTop(this.value)">
</label>
<label>
<span>toggle signal led</span>
<input type="color" onchange="colorBottom(this.value)">
</label>
</footer> </footer>
</article> </article>
</div> </div>
@ -413,13 +421,31 @@
ws.send(data); ws.send(data);
} }
function gpio() { function gpio(val) {
if (document.getElementById('led-switch').checked) if (val)
wsWrite('E'); wsWrite('E');
else else
wsWrite('D'); wsWrite('D');
} }
function colorTop(val) {
var header = new ArrayBuffer(8);
var headerview = new DataView(header);
headerview.setChar(0, 'T');
headerview.setInt32(4, parseInt(val.substring(1), 16));
console.log(buf2hex(header));
wsWrite(header);
}
function colorBottom(val) {
var header = new ArrayBuffer(8);
var headerview = new DataView(header);
headerview.setChar(0, 'B');
headerview.setInt32(4, parseInt(val.substring(1), 16));
console.log(buf2hex(header));
wsWrite(header);
}
window.onload = function () { window.onload = function () {
wsOpen(); wsOpen();
startPolling(); startPolling();