Compare commits
	
		
			11 commits
		
	
	
		
			stable
			...
			jedi/dev/t
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f6681d54de | |||
| d96504d3eb | |||
| e2e3b249bf | |||
| 874ca62eee | |||
| 22b240a472 | |||
| 4b23e5bc09 | |||
| b72426b9c7 | |||
| 7f422a2ddd | |||
| 769351684b | |||
| 78934b85c2 | |||
| e6d6757982 | 
					 14 changed files with 624 additions and 77 deletions
				
			
		|  | @ -9,19 +9,17 @@ steps: | ||||||
| - name: submodules | - name: submodules | ||||||
|   image: alpine/git |   image: alpine/git | ||||||
|   commands: |   commands: | ||||||
|   - git submodule update --init --recursive --depth 1 |   - git submodule update --init --recursive | ||||||
| 
 | 
 | ||||||
| - name: firmware | - name: firmware | ||||||
|   image: docker-repo.service.intern.lab.or.it:5000/fiatlux-build-env |   image: docker-repo.service.intern.lab.or.it:5000/fiatlux-build-env | ||||||
|   depends_on: [ submodules ] |   depends_on: [ submodules ] | ||||||
|   commands: |   commands: | ||||||
|   - export PATH=$(pwd)/modules/sdk/xtensa-lx106-elf/bin:$PATH |   - export PATH=$(pwd)/modules/sdk/xtensa-lx106-elf/bin:$PATH | ||||||
|   - apt update |  | ||||||
|   - apt install -y minify |  | ||||||
|   - make firmware -j$(nproc) |   - make firmware -j$(nproc) | ||||||
| 
 | 
 | ||||||
| - name: pcb | - name: pcb | ||||||
|   image: setsoft/kicad_auto:ki6 |   image: setsoft/kicad_auto | ||||||
|   commands: |   commands: | ||||||
|   - apt update |   - apt update | ||||||
|   - apt install -y make zip |   - apt install -y make zip | ||||||
|  | @ -64,6 +62,6 @@ steps: | ||||||
|     checksum: |     checksum: | ||||||
|       - sha512 |       - sha512 | ||||||
|       - md5 |       - md5 | ||||||
|     title: fiatlux |     title: buildtest | ||||||
|   when: |   when: | ||||||
|     event: tag |     event: tag | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -1,3 +1,4 @@ | ||||||
|  | 
 | ||||||
| .PHONY: firmware flash firmware_docker case pcb | .PHONY: firmware flash firmware_docker case pcb | ||||||
| 
 | 
 | ||||||
| all: firmware case pcb | all: firmware case pcb | ||||||
|  | @ -18,11 +19,6 @@ clean: | ||||||
| 	+@make -C firmware clean | 	+@make -C firmware clean | ||||||
| 	+@make -C pcb clean | 	+@make -C pcb clean | ||||||
| 
 | 
 | ||||||
| flash_docker: |  | ||||||
| 	sh -c "docker build -t fiatlux_firmware_env docker/firmware" |  | ||||||
| 	sh -c "docker run --volume "$$(pwd)"/firmware:/app/firmware --device=/dev/ttyUSB0 fiatlux_firmware_env make -C firmware flash" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| firmware_docker: | firmware_docker: | ||||||
| 	sh -c "docker build -t fiatlux_firmware_env docker/firmware" | 	sh -c "docker build -t fiatlux_firmware_env docker/firmware" | ||||||
| 	sh -c "docker run --volume "$$(pwd)"/firmware:/app/firmware fiatlux_firmware_env make -C firmware html all" | 	sh -c "docker run --volume "$$(pwd)"/firmware:/app/firmware fiatlux_firmware_env make -C firmware html all" | ||||||
|  |  | ||||||
|  | @ -2,11 +2,11 @@ PROGRAM=fiatlux | ||||||
| 
 | 
 | ||||||
| EXTRA_CFLAGS=-O3 -Ibuild/gen -DLWIP_NETIF_HOSTNAME=1 | EXTRA_CFLAGS=-O3 -Ibuild/gen -DLWIP_NETIF_HOSTNAME=1 | ||||||
| 
 | 
 | ||||||
| EXTRA_COMPONENTS=extras/i2s_dma extras/ws2812_i2s extras/dhcpserver extras/rboot-ota extras/mbedtls extras/httpd extras/sntp extras/cpp_support extras/paho_mqtt_c | EXTRA_COMPONENTS=extras/i2s_dma extras/ws2812_i2s extras/dhcpserver extras/rboot-ota extras/mbedtls extras/httpd extras/sntp extras/cpp_support | ||||||
| 
 | 
 | ||||||
| LIBS = hal m | LIBS = hal m | ||||||
| 
 | 
 | ||||||
| FLASH_MODE = qio | FLASH_MODE = dio | ||||||
| 
 | 
 | ||||||
| include ../modules/rtos/common.mk | include ../modules/rtos/common.mk | ||||||
| 
 | 
 | ||||||
|  | @ -15,7 +15,7 @@ html: build/gen/fsdata.c | ||||||
| build/gen/fsdata.c: webdir/index.html webdir/404.html webdir/css/picnic.min.css webdir/css/style.css webdir/js/smoothie_min.js | build/gen/fsdata.c: webdir/index.html webdir/404.html webdir/css/picnic.min.css webdir/css/style.css webdir/js/smoothie_min.js | ||||||
| 	@echo "Generating fsdata.." | 	@echo "Generating fsdata.." | ||||||
| 	@mkdir -p $(dir $@) | 	@mkdir -p $(dir $@) | ||||||
| 	@./mkwebfs.py --gzip --minify -o $@ $^ | 	@./mkwebfs.py --gzip -o $@ $^ | ||||||
| 
 | 
 | ||||||
| test: unittest systest | test: unittest systest | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,8 @@ | ||||||
| #include <espressif/esp_common.h> | #include <espressif/esp_common.h> | ||||||
| #include <esp/uart.h> | #include <esp/uart.h> | ||||||
| 
 | 
 | ||||||
|  | #include "rboot-api.h" | ||||||
|  | 
 | ||||||
| void user_init(void) | void user_init(void) | ||||||
| { | { | ||||||
|     uart_set_baud(0, 115200); |     uart_set_baud(0, 115200); | ||||||
|  | @ -27,4 +29,15 @@ void user_init(void) | ||||||
|     xTaskCreate(&httpd_task, "httpd_task", 1024, NULL, 2, NULL); |     xTaskCreate(&httpd_task, "httpd_task", 1024, NULL, 2, NULL); | ||||||
| 
 | 
 | ||||||
|     xTaskCreate(&lux_task, "lux_task", 512, NULL, 1, NULL); |     xTaskCreate(&lux_task, "lux_task", 512, NULL, 1, NULL); | ||||||
|  | 
 | ||||||
|  |     rboot_config conf = rboot_get_config(); | ||||||
|  |     printf("\r\n\r\nOTA Basic demo.\r\nCurrently running on flash slot %d / %d.\r\n\r\n", | ||||||
|  |            conf.current_rom, conf.count); | ||||||
|  | 
 | ||||||
|  |     printf("Image addresses in flash:\r\n"); | ||||||
|  |     for(int i = 0; i <conf.count; i++) { | ||||||
|  |         printf("%c%d: offset 0x%08x\r\n", i == conf.current_rom ? '*':' ', i, conf.roms[i]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     printf("profit!\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										295
									
								
								firmware/lux.cpp
									
										
									
									
									
								
							
							
						
						
									
										295
									
								
								firmware/lux.cpp
									
										
									
									
									
								
							|  | @ -9,24 +9,297 @@ | ||||||
| #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}}; | ||||||
|  |     colour.red = 0; | ||||||
|  |     colour.green = 0; | ||||||
|  |     colour.blue = 0; | ||||||
|  |     colour.white = 8; | ||||||
|  | 
 | ||||||
|  |     return colour; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static apa10xx_pixel_t next_color(int i) { | ||||||
|  |     apa10xx_pixel_t colour; | ||||||
|  |     colour.global.mod = 8; | ||||||
|  |     colour.r = 16; | ||||||
|  |     colour.g = 16; | ||||||
|  |     colour.b = 16; | ||||||
|  | 
 | ||||||
|  |     return colour; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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) { | ||||||
|  |     fiatlux::signal::write_data(state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extern "C" void white_led(bool state) { | ||||||
|     gpio_write(signal_led_pin, !state); |     gpio_write(signal_led_pin, !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 = 40; | ||||||
|  |     auto ret = sysparam_get_int32("lux_ws2812_number", &lux_ws2812_number); | ||||||
|  |     if(ret != SYSPARAM_OK) | ||||||
|  |         lux_ws2812_number = 40; | ||||||
|  | 
 | ||||||
|  |     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); | ||||||
|  |             } | ||||||
|  |             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); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | @ -2,7 +2,6 @@ | ||||||
| import os | import os | ||||||
| import gzip | import gzip | ||||||
| import argparse | import argparse | ||||||
| import subprocess |  | ||||||
| 
 | 
 | ||||||
| parser = argparse.ArgumentParser() | parser = argparse.ArgumentParser() | ||||||
| parser.add_argument('-o', '--output', help='Output file name', default='stdout') | parser.add_argument('-o', '--output', help='Output file name', default='stdout') | ||||||
|  | @ -10,9 +9,6 @@ parser.add_argument('-W', '--webroot', help='Output file name', default='webdir/ | ||||||
| parser.add_argument('--gzip', dest='gzip', action='store_true') | parser.add_argument('--gzip', dest='gzip', action='store_true') | ||||||
| parser.add_argument('--no-gzip', dest='gzip', action='store_false') | parser.add_argument('--no-gzip', dest='gzip', action='store_false') | ||||||
| parser.set_defaults(gzip=False) | parser.set_defaults(gzip=False) | ||||||
| parser.add_argument('--minify', dest='minify', action='store_true') |  | ||||||
| parser.add_argument('--no-minify', dest='minify', action='store_false') |  | ||||||
| parser.set_defaults(minify=False) |  | ||||||
| parser.add_argument('--header', dest='header', action='store_true') | parser.add_argument('--header', dest='header', action='store_true') | ||||||
| parser.add_argument('--no-header', dest='header', action='store_false') | parser.add_argument('--no-header', dest='header', action='store_false') | ||||||
| parser.set_defaults(header=True) | parser.set_defaults(header=True) | ||||||
|  | @ -20,31 +16,6 @@ parser.add_argument('input', nargs='+', default=os.getcwd()) | ||||||
| args = parser.parse_args() | args = parser.parse_args() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def mimeFromName(name): |  | ||||||
|     if name.endswith(".html") or name.endswith(".htm") or name.endswith(".shtml") or name.endswith( |  | ||||||
|             ".shtm") or name.endswith(".ssi"): |  | ||||||
|         return "text/html" |  | ||||||
|     if name.endswith(".js"): |  | ||||||
|         return "application/x-javascript" |  | ||||||
|     if name.endswith(".css"): |  | ||||||
|         return "text/css" |  | ||||||
|     if name.endswith(".ico"): |  | ||||||
|         return "image/x-icon" |  | ||||||
|     if name.endswith(".gif"): |  | ||||||
|         return "image/gif" |  | ||||||
|     if name.endswith(".png"): |  | ||||||
|         return "image/png" |  | ||||||
|     if name.endswith(".jpg"): |  | ||||||
|         return "image/jpeg" |  | ||||||
|     if name.endswith(".bmp"): |  | ||||||
|         return "image/bmp" |  | ||||||
|     if name.endswith(".class"): |  | ||||||
|         return "application/octet-stream" |  | ||||||
|     if name.endswith(".ram"): |  | ||||||
|         return "audio/x-pn-realaudio" |  | ||||||
|     return "text/plain" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def dumpBin2CHex(f, b): | def dumpBin2CHex(f, b): | ||||||
|     oStr = "\t" |     oStr = "\t" | ||||||
|     n = 0 |     n = 0 | ||||||
|  | @ -70,28 +41,40 @@ for file in httpFiles: | ||||||
|     webPath = ("/" + file.removeprefix(args.webroot)).replace("//", "/") |     webPath = ("/" + file.removeprefix(args.webroot)).replace("//", "/") | ||||||
|     print("{} > {}".format(file, webPath)) |     print("{} > {}".format(file, webPath)) | ||||||
| 
 | 
 | ||||||
|     mimeType = mimeFromName(file) |  | ||||||
| 
 |  | ||||||
|     if args.header: |     if args.header: | ||||||
|         if ("404" in file): |         if ("404" in file): | ||||||
|             response = b'HTTP/1.0 404 File not found\r\n' |             response = b'HTTP/1.0 404 File not found\r\n' | ||||||
|         else: |         else: | ||||||
|             response = b'HTTP/1.0 200 OK\r\n' |             response = b'HTTP/1.0 200 OK\r\n' | ||||||
|         response += b"lwIP/1.4.1 (http://savannah.nongnu.org/projects/lwip)\r\n" |         response += b"lwIP/1.4.1 (http://savannah.nongnu.org/projects/lwip)\r\n" | ||||||
|         response += b'Content-type: ' + mimeType.encode() + b'\r\n' |         fext = file.split('.')[-1] | ||||||
|  |         ctype = b'Content-type: text/plain\r\n' | ||||||
|  |         if (fext.endswith("html") or fext.endswith("htm") or fext.endswith("shtml") or fext.endswith( | ||||||
|  |                 "shtm") or fext.endswith("ssi")): | ||||||
|  |             ctype = b'Content-type: text/html\r\n' | ||||||
|  |         if (fext.endswith("js")): | ||||||
|  |             ctype = b'Content-type: application/x-javascript\r\n' | ||||||
|  |         if (fext.endswith("css")): | ||||||
|  |             ctype = b'Content-type: text/css\r\n' | ||||||
|  |         if (fext.endswith("ico")): | ||||||
|  |             ctype = b'Content-type: image/x-icon\r\n' | ||||||
|  |         if (fext.endswith("gif")): | ||||||
|  |             ctype = b'Content-type: image/gif\r\n' | ||||||
|  |         if (fext.endswith("png")): | ||||||
|  |             ctype = b'Content-type: image/png\r\n' | ||||||
|  |         if(fext.endswith("jpg")): | ||||||
|  |             ctype = b'Content-type: image/jpeg\r\n' | ||||||
|  |         if(fext.endswith("bmp")): | ||||||
|  |             ctype = b'Content-type: image/bmp\r\n' | ||||||
|  |         if(fext.endswith("class")): | ||||||
|  |             ctype = b'Content-type: application/octet-stream\r\n' | ||||||
|  |         if(fext.endswith("ram")): | ||||||
|  |             ctype = b'Content-type: audio/x-pn-realaudio\r\n' | ||||||
|  |         response += ctype | ||||||
| 
 | 
 | ||||||
|         binFile = open(file, 'rb') |         binFile = open(file, 'rb') | ||||||
|         binData = binFile.read() |         binData = binFile.read() | ||||||
|         compEff = False |         compEff = False | ||||||
|         if args.minify: |  | ||||||
|             p = subprocess.Popen(["minify", "--html-keep-document-tags", "--mime", mimeType], stdin=subprocess.PIPE, |  | ||||||
|                                  stdout=subprocess.PIPE) |  | ||||||
|             minData = p.communicate(binData)[0] |  | ||||||
|             if len(minData) < len(binData): |  | ||||||
|                 print("- Minify: {} -> {}".format(len(binData), len(minData))) |  | ||||||
|                 compEff = True |  | ||||||
|                 binData = minData |  | ||||||
| 
 |  | ||||||
|         if args.gzip: |         if args.gzip: | ||||||
|             compData = gzip.compress(binData, 9) |             compData = gzip.compress(binData, 9) | ||||||
|             if len(compData) < len(binData): |             if len(compData) < len(binData): | ||||||
|  | @ -120,8 +103,7 @@ for file in httpFiles: | ||||||
|         f_fsdata_c.write("};\n\n") |         f_fsdata_c.write("};\n\n") | ||||||
| 
 | 
 | ||||||
|         f_fsdata_c.write("const struct fsdata_file {}[] = {{{{\n  {},\n  {}, {} + {}, sizeof({}) - {}, 1 }}}};\n\n" |         f_fsdata_c.write("const struct fsdata_file {}[] = {{{{\n  {},\n  {}, {} + {}, sizeof({}) - {}, 1 }}}};\n\n" | ||||||
|                          .format(escFileFile, lastFileStruct, escFileData, escFileData, len(fnameBin), escFileData, |                 .format(escFileFile, lastFileStruct, escFileData, escFileData, len(fnameBin), escFileData, len(fnameBin))) | ||||||
|                                  len(fnameBin))) |  | ||||||
|         # TODO: The last value is 1 if args.header == True |         # TODO: The last value is 1 if args.header == True | ||||||
|         lastFileStruct = escFileFile |         lastFileStruct = escFileFile | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ | ||||||
| void system_clear_config() { | void system_clear_config() { | ||||||
|     vPortEnterCritical(); |     vPortEnterCritical(); | ||||||
|     uint32_t num_sectors = 0x2000 / sdk_flashchip.sector_size; |     uint32_t num_sectors = 0x2000 / sdk_flashchip.sector_size; | ||||||
|  |     //uint32_t start = sdk_flashchip.chip_size - num_sectors * sdk_flashchip.sector_size;
 | ||||||
|     uint32_t start = 0x00100000; |     uint32_t start = 0x00100000; | ||||||
|     for (uint32_t i = 0; i < num_sectors; i++) { |     for (uint32_t i = 0; i < num_sectors; i++) { | ||||||
|         spiflash_erase_sector(start + i * sdk_flashchip.sector_size); |         spiflash_erase_sector(start + i * sdk_flashchip.sector_size); | ||||||
|  | @ -42,6 +43,7 @@ void system_init_config() { | ||||||
|     if(sysparam_get_info(&base_addr, &num_sectors) != SYSPARAM_OK) { |     if(sysparam_get_info(&base_addr, &num_sectors) != SYSPARAM_OK) { | ||||||
|         syslog("Warning: WiFi config, sysparam not initialized\n"); |         syslog("Warning: WiFi config, sysparam not initialized\n"); | ||||||
|         num_sectors = 0x2000 / sdk_flashchip.sector_size; |         num_sectors = 0x2000 / sdk_flashchip.sector_size; | ||||||
|  |         //base_addr = sdk_flashchip.chip_size - (5 + num_sectors) * sdk_flashchip.sector_size;
 | ||||||
|         if(sysparam_create_area(base_addr, num_sectors, true) == SYSPARAM_OK) { |         if(sysparam_create_area(base_addr, num_sectors, true) == SYSPARAM_OK) { | ||||||
|             sysparam_init(base_addr, 0); |             sysparam_init(base_addr, 0); | ||||||
|         } |         } | ||||||
|  | @ -49,7 +51,7 @@ void system_init_config() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define MAX_IMAGE_SIZE 0x100000 | #define MAX_IMAGE_SIZE 0x100000 /*1MB images max at the moment */ | ||||||
| 
 | 
 | ||||||
| struct { | struct { | ||||||
|     rboot_write_status status; |     rboot_write_status status; | ||||||
|  | @ -67,10 +69,14 @@ void system_otaflash_init() { | ||||||
|     otaflash_context.status = rboot_write_init(otaflash_context.base); |     otaflash_context.status = rboot_write_init(otaflash_context.base); | ||||||
|     otaflash_context.head = otaflash_context.base; |     otaflash_context.head = otaflash_context.base; | ||||||
|     otaflash_context.seq = 0; |     otaflash_context.seq = 0; | ||||||
|  | 
 | ||||||
|  |     //printf("slot: %u, base: %x, sector: %u\n", otaflash_context.slot, otaflash_context.base,
 | ||||||
|  |     //       otaflash_context.status.start_sector);
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum return_code system_otaflash_chunk(uint8_t *data, uint16_t len, uint16_t seq, uint32_t hash, uint16_t *ack) { | enum return_code system_otaflash_chunk(uint8_t *data, uint16_t len, uint16_t seq, uint32_t hash, uint16_t *ack) { | ||||||
|     uint32_t local_hash = crc32(data, len); |     uint32_t local_hash = crc32(data, len); | ||||||
|  |     //printf("@%x seq: %u, len: %u, hash: %x =? %x\n", otaflash_context.head, seq, len, hash, local_hash);
 | ||||||
|     if(hash == local_hash && otaflash_context.seq == seq) { |     if(hash == local_hash && otaflash_context.seq == seq) { | ||||||
|         if(otaflash_context.head % SECTOR_SIZE == 0) { |         if(otaflash_context.head % SECTOR_SIZE == 0) { | ||||||
|             sdk_spi_flash_erase_sector(otaflash_context.head / SECTOR_SIZE); |             sdk_spi_flash_erase_sector(otaflash_context.head / SECTOR_SIZE); | ||||||
|  |  | ||||||
|  | @ -204,7 +204,21 @@ void websocket_task(void *pvParameter) { | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /*vTaskDelayMs(250);
 | ||||||
|  |         { | ||||||
|  |             uint8_t response[3]; | ||||||
|  |             uint16_t val; | ||||||
|  |             val = sdk_system_adc_read(); | ||||||
|  |             response[2] = (uint8_t) val; | ||||||
|  |             response[1] = val >> 8; | ||||||
|  |             response[0] = 'V'; | ||||||
|  |             LOCK_TCPIP_CORE(); | ||||||
|  |             websocket_write(pcb, response, 3, WS_BIN_MODE); | ||||||
|  |             UNLOCK_TCPIP_CORE(); | ||||||
|  |         }*/ | ||||||
|         vTaskDelayMs(500); |         vTaskDelayMs(500); | ||||||
|  |         //printf("9: %d\n",gpio_read(9));
 | ||||||
|  |         //printf("10: %d\n",gpio_read(10));
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     syslog_detach(); |     syslog_detach(); | ||||||
|  | @ -245,9 +259,16 @@ void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len, | ||||||
|     ret = ERROR; |     ret = ERROR; | ||||||
|     val = 0; |     val = 0; | ||||||
| 
 | 
 | ||||||
|  |     int8_t en = 0; | ||||||
|     bool togl = false; |     bool togl = false; | ||||||
| 
 | 
 | ||||||
|     switch (data[0]) { |     switch (data[0]) { | ||||||
|  |         case 'V': // ADC
 | ||||||
|  |             /* This should be done on a separate thread in 'real' applications */ | ||||||
|  |             cmd = 'V'; | ||||||
|  |             ret = OK; | ||||||
|  |             val = sdk_system_adc_read(); | ||||||
|  |             break; | ||||||
|         case 'R': // Restart
 |         case 'R': // Restart
 | ||||||
|             cmd = 'R'; |             cmd = 'R'; | ||||||
|             ret = OK; |             ret = OK; | ||||||
|  | @ -270,6 +291,18 @@ void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len, | ||||||
|             ret = OK; |             ret = OK; | ||||||
|             val = 0; |             val = 0; | ||||||
|             break; |             break; | ||||||
|  |         case 'd': // Disable LED
 | ||||||
|  |             signal_led(false); | ||||||
|  |             cmd = 'G'; | ||||||
|  |             ret = OK; | ||||||
|  |             val = 1; | ||||||
|  |             break; | ||||||
|  |         case 'e': // Enable LED
 | ||||||
|  |             signal_led(true); | ||||||
|  |             cmd = 'G'; | ||||||
|  |             ret = OK; | ||||||
|  |             val = 0; | ||||||
|  |             break; | ||||||
|         case 'F': |         case 'F': | ||||||
|             togl = !togl; |             togl = !togl; | ||||||
|             signal_led(togl); |             signal_led(togl); | ||||||
|  | @ -292,6 +325,46 @@ void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len, | ||||||
|             } |             } | ||||||
|             cmd = 'C'; |             cmd = 'C'; | ||||||
|             break; |             break; | ||||||
|  |         case 'S': { | ||||||
|  |             if(data[1] == 'E') | ||||||
|  |                 en = 1; | ||||||
|  |             char *ssid = &data[2]; | ||||||
|  |             size_t ssid_len = strlen(ssid); | ||||||
|  |             char *password = &data[3 + ssid_len]; | ||||||
|  |             size_t password_len = strlen(password); | ||||||
|  |             (void) password_len; | ||||||
|  | 
 | ||||||
|  |             sysparam_set_int8("wifi_sta_enable", en); | ||||||
|  |             sysparam_set_string("wifi_sta_ssid", ssid); | ||||||
|  |             sysparam_set_string("wifi_sta_password", password); | ||||||
|  |         } | ||||||
|  |             cmd = 'S'; | ||||||
|  |             break; | ||||||
|  |         case 'A': { | ||||||
|  |             if(data[1] == 'E') | ||||||
|  |                 en = 1; | ||||||
|  |             char *ssid = &data[2]; | ||||||
|  |             size_t ssid_len = strlen(ssid); | ||||||
|  |             char *password = &data[3 + ssid_len]; | ||||||
|  |             size_t password_len = strlen(password); | ||||||
|  |             (void) password_len; | ||||||
|  | 
 | ||||||
|  |             sysparam_set_int8("wifi_ap_enable", en); | ||||||
|  |             sysparam_set_string("wifi_ap_ssid", ssid); | ||||||
|  |             sysparam_set_string("wifi_ap_password", password); | ||||||
|  | 
 | ||||||
|  |             /*uint8_t ap_disable_if_sta = 0;
 | ||||||
|  |             uint8_t ssid_hidden = 0; | ||||||
|  |             uint8_t dns_enable = 0; | ||||||
|  |             uint8_t mdns_enable = 0;*/ | ||||||
|  | 
 | ||||||
|  |             //sysparam_set_int8("wifi_ap_disable_if_sta", ap_disable_if_sta);
 | ||||||
|  |             //sysparam_set_int8("wifi_ap_ssid_hidden", ssid_hidden);
 | ||||||
|  |             //sysparam_set_int8("wifi_ap_dns", dns_enable);
 | ||||||
|  |             //sysparam_set_int8("wifi_ap_mdns", mdns_enable);
 | ||||||
|  |         } | ||||||
|  |             cmd = 'A'; | ||||||
|  |             break; | ||||||
|         default: |         default: | ||||||
|             printf("[websocket_callback]:\n%.*s\n", (int) data_len, (char *) data); |             printf("[websocket_callback]:\n%.*s\n", (int) data_len, (char *) data); | ||||||
|             printf("Unknown command %c\n", data[0]); |             printf("Unknown command %c\n", data[0]); | ||||||
|  | @ -327,11 +400,36 @@ void websocket_open_cb(struct tcp_pcb *pcb, const char *uri) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*const char *gpio_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
 | ||||||
|  |     for (int i = 0; i < iNumParams; i++) { | ||||||
|  |         if(strcmp(pcParam[i], "on") == 0) { | ||||||
|  |             uint8_t gpio_num = atoi(pcValue[i]); | ||||||
|  |             gpio_enable(gpio_num, GPIO_OUTPUT); | ||||||
|  |             gpio_write(gpio_num, true); | ||||||
|  |         } else if(strcmp(pcParam[i], "off") == 0) { | ||||||
|  |             uint8_t gpio_num = atoi(pcValue[i]); | ||||||
|  |             gpio_enable(gpio_num, GPIO_OUTPUT); | ||||||
|  |             gpio_write(gpio_num, false); | ||||||
|  |         } else if(strcmp(pcParam[i], "toggle") == 0) { | ||||||
|  |             uint8_t gpio_num = atoi(pcValue[i]); | ||||||
|  |             gpio_enable(gpio_num, GPIO_OUTPUT); | ||||||
|  |             gpio_toggle(gpio_num); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return "/index.html"; | ||||||
|  | }*/ | ||||||
|  | 
 | ||||||
| extern "C" void httpd_task(void *pvParameters) { | extern "C" void httpd_task(void *pvParameters) { | ||||||
|     (void) pvParameters; |     (void) pvParameters; | ||||||
| 
 | 
 | ||||||
|     while (!uxSemaphoreGetCount(wifi_available_semaphore)) |     while (!uxSemaphoreGetCount(wifi_available_semaphore)) | ||||||
|         vTaskDelay(500 / portTICK_PERIOD_MS); |         vTaskDelay(500 / portTICK_PERIOD_MS); | ||||||
|  |     /*tCGI pCGIs[] = {
 | ||||||
|  |             {"/gpio", (tCGIHandler) gpio_cgi_handler}, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // register handlers and start the server
 | ||||||
|  |     http_set_cgi_handlers(pCGIs, sizeof(pCGIs) / sizeof(pCGIs[0]));*/ | ||||||
|     websocket_register_callbacks((tWsOpenHandler) websocket_open_cb, (tWsHandler) websocket_cb); |     websocket_register_callbacks((tWsOpenHandler) websocket_open_cb, (tWsHandler) websocket_cb); | ||||||
|     httpd_init(); |     httpd_init(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,6 +17,8 @@ | ||||||
|     <label for="bmenub" class="burger pseudo button">☰</label> |     <label for="bmenub" class="burger pseudo button">☰</label> | ||||||
|     <div class="menu"> |     <div class="menu"> | ||||||
|         <a href="/#" class="button icon-picture">Dashboard</a> |         <a href="/#" class="button icon-picture">Dashboard</a> | ||||||
|  |         <a href="/#io" class="button icon-puzzle">I/O</a> | ||||||
|  |         <a href="/#wifi" class="button icon-puzzle">Wifi Settings</a> | ||||||
|         <a href="/#ota" class="button icon-picture">System</a> |         <a href="/#ota" class="button icon-picture">System</a> | ||||||
|     </div> |     </div> | ||||||
| </nav> | </nav> | ||||||
|  | @ -75,6 +77,125 @@ | ||||||
|         </article> |         </article> | ||||||
| 
 | 
 | ||||||
|     </section> |     </section> | ||||||
|  |     <section id="io"> | ||||||
|  |         <h2>I/O</h2> | ||||||
|  |         <article class="card"> | ||||||
|  |             <header> | ||||||
|  |                 <h3>Protocols</h3> | ||||||
|  |             </header> | ||||||
|  |             <div class="table"> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>MQTT</label> | ||||||
|  |                     <span><input type="checkbox" class="plain"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span><input type="reset" class="button"/></span> | ||||||
|  |                     <span><input type="submit" value="Save"></span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </article> | ||||||
|  |         <article class="card"> | ||||||
|  |             <header> | ||||||
|  |                 <h3>Station Mode <span class="label success">current connection</span></h3> | ||||||
|  |             </header> | ||||||
|  |             <div class="table"> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>WS2812 via I2S</label> | ||||||
|  |                     <span><input type="checkbox" class="plain"/></span> | ||||||
|  |                     <span><input type="color"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>APA102C via SPI</label> | ||||||
|  |                     <span><input type="checkbox" class="plain"/></span> | ||||||
|  |                     <span><input type="color"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>6 Channel SPI Dimmer</label> | ||||||
|  |                     <span><input type="checkbox" class="plain"/></span> | ||||||
|  |                     <span><input type="color"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>Binary Output on GPIO4</label> | ||||||
|  |                     <span><input type="checkbox" class="plain"/></span> | ||||||
|  |                     <span><button class="toggle button">Toggle</button></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>Binary Output on GPIO5</label> | ||||||
|  |                     <span><input type="checkbox" class="plain"/></span> | ||||||
|  |                     <span><button class="toggle button">Toggle</button></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span><input type="reset" class="button"/></span> | ||||||
|  |                     <span><input type="submit" value="Save"></span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </article> | ||||||
|  |     </section> | ||||||
|  |     <section id="wifi"> | ||||||
|  |         <h2>Wifi Settings</h2> | ||||||
|  |         <article class="card"> | ||||||
|  |             <header> | ||||||
|  |                 <h3>AP Mode</h3> | ||||||
|  |             </header> | ||||||
|  |             <div class="table"> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>Enable</label> | ||||||
|  |                     <span><input id="ap_toggle" type="checkbox" class="plain"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>SSID</label> | ||||||
|  |                     <span><input id="ap_ssid" type="text" placeholder="SSID"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>Password</label> | ||||||
|  |                     <span><input id="ap_pw" type="password" placeholder="Password"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span>AP IP</span> | ||||||
|  |                     <span><span class="postfill_apip">N/A</span></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span>AP MAC</span> | ||||||
|  |                     <span><span class="postfill_apmac">N/A</span></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span><input type="reset" class="button"/></span> | ||||||
|  |                     <span><input onclick="ap_update();" type="submit" value="Save"></span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </article> | ||||||
|  |         <article class="card"> | ||||||
|  |             <header> | ||||||
|  |                 <h3>Station Mode <span class="label success">current connection</span></h3> | ||||||
|  |             </header> | ||||||
|  |             <div class="table"> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>Eanable</label> | ||||||
|  |                     <span><input id="sta_toggle" type="checkbox" class="plain"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>SSID</label> | ||||||
|  |                     <span><input id="sta_ssid" type="text" placeholder="SSID"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <label>Password</label> | ||||||
|  |                     <span><input id="sta_pw" type="password" placeholder="Password"/></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span>Sation IP</span> | ||||||
|  |                     <span><span class="postfill_staip">N/A</span></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span>Station MAC</span> | ||||||
|  |                     <span><span class="postfill_stamac">N/A</span></span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="row"> | ||||||
|  |                     <span><input type="reset" class="button"/></span> | ||||||
|  |                     <span><input onclick="sta_update();" type="submit" value="Save"></span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </article> | ||||||
|  |     </section> | ||||||
|     <section id="dashboard"> |     <section id="dashboard"> | ||||||
|         <h2>Status</h2> |         <h2>Status</h2> | ||||||
|         <div class="flex"> |         <div class="flex"> | ||||||
|  | @ -180,6 +301,10 @@ | ||||||
|                             <input type="checkbox" name="onoffswitch" id="led-switch" onclick="gpio()"> |                             <input type="checkbox" name="onoffswitch" id="led-switch" onclick="gpio()"> | ||||||
|                             <span class="toggle button">toggle signal led</span> |                             <span class="toggle button">toggle signal led</span> | ||||||
|                         </label> |                         </label> | ||||||
|  |                         <label> | ||||||
|  |                             <input type="checkbox" name="whiteswitch" id="white-switch" onclick="leds()"> | ||||||
|  |                             <span class="toggle button">toggle white leds</span> | ||||||
|  |                         </label> | ||||||
|                     </footer> |                     </footer> | ||||||
|                 </article> |                 </article> | ||||||
|             </div> |             </div> | ||||||
|  | @ -220,7 +345,7 @@ | ||||||
|         sbox = document.getElementById('status_box'); |         sbox = document.getElementById('status_box'); | ||||||
|         sbox.className = "label " + cls; |         sbox.className = "label " + cls; | ||||||
|         sbox.innerHTML = text; |         sbox.innerHTML = text; | ||||||
|         console.info(text); |         //console.info(text); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function startPolling() { |     function startPolling() { | ||||||
|  | @ -325,11 +450,58 @@ | ||||||
|             wsWrite('D'); |             wsWrite('D'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     function leds() { | ||||||
|  |         if (document.getElementById('white-switch').checked) | ||||||
|  |             wsWrite('e'); | ||||||
|  |         else | ||||||
|  |             wsWrite('d'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     window.onload = function () { |     window.onload = function () { | ||||||
|         wsOpen(); |         wsOpen(); | ||||||
|         startPolling(); |         startPolling(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     var sta_toggle = document.getElementById("sta_toggle"); | ||||||
|  |     var sta_ssid = document.getElementById("sta_ssid"); | ||||||
|  |     var sta_pw = document.getElementById("sta_pw"); | ||||||
|  | 
 | ||||||
|  |     function sta_update() { | ||||||
|  |         var en = sta_toggle.checked; | ||||||
|  | 
 | ||||||
|  |         const ssid = sta_ssid.value; | ||||||
|  |         const password = sta_pw.value; | ||||||
|  | 
 | ||||||
|  |         const buffer = new ArrayBuffer(ssid.length + password.length + 4); | ||||||
|  |         const view1 = new DataView(buffer); | ||||||
|  |         var tx_len = 0; | ||||||
|  |         view1.setChar(tx_len++, 'S'); | ||||||
|  |         view1.setChar(tx_len++, (en ? "E" : "D")); | ||||||
|  |         tx_len = view1.setString(tx_len, ssid); | ||||||
|  |         tx_len = view1.setString(tx_len, password); | ||||||
|  |         wsWrite(buffer); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     var ap_toggle = document.getElementById("ap_toggle"); | ||||||
|  |     var ap_ssid = document.getElementById("ap_ssid"); | ||||||
|  |     var ap_pw = document.getElementById("ap_pw"); | ||||||
|  | 
 | ||||||
|  |     function ap_update() { | ||||||
|  |         var en = ap_toggle.checked; | ||||||
|  | 
 | ||||||
|  |         const ssid = ap_ssid.value; | ||||||
|  |         const password = ap_pw.value; | ||||||
|  | 
 | ||||||
|  |         const buffer = new ArrayBuffer(ssid.length + password.length + 4); | ||||||
|  |         const view1 = new DataView(buffer); | ||||||
|  |         var tx_len = 0; | ||||||
|  |         view1.setChar(tx_len++, 'A'); | ||||||
|  |         view1.setChar(tx_len++, (en ? "E" : "D")); | ||||||
|  |         tx_len = view1.setString(tx_len, ssid); | ||||||
|  |         tx_len = view1.setString(tx_len, password); | ||||||
|  |         wsWrite(buffer); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     var makeCRCTable = function () { |     var makeCRCTable = function () { | ||||||
|         var c; |         var c; | ||||||
|         var crcTable = []; |         var crcTable = []; | ||||||
|  | @ -358,6 +530,8 @@ | ||||||
|     var firmware_file; |     var firmware_file; | ||||||
| 
 | 
 | ||||||
|     function load_firmware(evt) { |     function load_firmware(evt) { | ||||||
|  |         //console.log("load_firmware", evt); | ||||||
|  | 
 | ||||||
|         var file = evt.target.files[0]; |         var file = evt.target.files[0]; | ||||||
|         if (!file) { |         if (!file) { | ||||||
|             return; |             return; | ||||||
|  | @ -395,11 +569,14 @@ | ||||||
|                 reject({frame_error: i}); |                 reject({frame_error: i}); | ||||||
|             }, 2000); |             }, 2000); | ||||||
|             wsWrite(frame.buffer); |             wsWrite(frame.buffer); | ||||||
|  |             //build packet: type, seq, len, hash, data | ||||||
|  |             console.log(i, (end - begin), crc32(slice), (100 * end / buf.byteLength) + "%"); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function transmit_firmware_final(buf, hash) { |     function transmit_firmware_final(buf, hash) { | ||||||
|         return new Promise((resolve, reject) => { |         return new Promise((resolve, reject) => { | ||||||
|  |             console.log("final: ", buf.byteLength, hash.toString(16)); | ||||||
|             var frame = new ArrayBuffer(12); |             var frame = new ArrayBuffer(12); | ||||||
|             var headerview = new DataView(frame); |             var headerview = new DataView(frame); | ||||||
|             headerview.setChar(0, 'C'); |             headerview.setChar(0, 'C'); | ||||||
|  | @ -416,8 +593,11 @@ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function transmit_firmware(evt) { |     function transmit_firmware(evt) { | ||||||
|         console.log("transmit_firmware begin"); |         console.log("transmit_firmware", evt); | ||||||
|         if (firmware_file) { |         if (firmware_file) { | ||||||
|  |             console.log("len", firmware_file.byteLength); | ||||||
|  |             //console.log(crc32(firmware_file)); | ||||||
|  | 
 | ||||||
|             (async () => { |             (async () => { | ||||||
|                 const ash = crc32(firmware_file); |                 const ash = crc32(firmware_file); | ||||||
|                 for (var i = 0; i * chunk_size < firmware_file.byteLength; i++) { |                 for (var i = 0; i * chunk_size < firmware_file.byteLength; i++) { | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								firmware/webdir/index.htmll
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								firmware/webdir/index.htmll
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -34,6 +34,8 @@ char *wifi_ap_password = nullptr; | ||||||
| SemaphoreHandle_t wifi_available_semaphore = nullptr; | SemaphoreHandle_t wifi_available_semaphore = nullptr; | ||||||
| 
 | 
 | ||||||
| [[noreturn]] static void dns_task(void *pvParameters) { | [[noreturn]] static void dns_task(void *pvParameters) { | ||||||
|  |     printf("run dns task\n"); | ||||||
|  | 
 | ||||||
|     char *wifi_ap_ip_addr = nullptr; |     char *wifi_ap_ip_addr = nullptr; | ||||||
|     sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); |     sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); | ||||||
|     if(!wifi_ap_ip_addr) { |     if(!wifi_ap_ip_addr) { | ||||||
|  | @ -271,6 +273,7 @@ extern "C" void wifi_task(void *pvParameters) { | ||||||
|         if(wifi_ap_channel < 1 || wifi_ap_channel > 14) { |         if(wifi_ap_channel < 1 || wifi_ap_channel > 14) { | ||||||
|             wifi_ap_channel = 6; |             wifi_ap_channel = 6; | ||||||
|         } |         } | ||||||
|  |         wifi_ap_channel = 3; | ||||||
| 
 | 
 | ||||||
|         int8_t wifi_ap_authmode = AUTH_WPA_WPA2_PSK; |         int8_t wifi_ap_authmode = AUTH_WPA_WPA2_PSK; | ||||||
|         sysparam_get_int8("wifi_ap_authmode", &wifi_ap_authmode); |         sysparam_get_int8("wifi_ap_authmode", &wifi_ap_authmode); | ||||||
|  | @ -284,6 +287,7 @@ extern "C" void wifi_task(void *pvParameters) { | ||||||
|         if(wifi_ap_max_conn < 1 || wifi_ap_max_conn > 8) { |         if(wifi_ap_max_conn < 1 || wifi_ap_max_conn > 8) { | ||||||
|             wifi_ap_max_conn = 3; |             wifi_ap_max_conn = 3; | ||||||
|         } |         } | ||||||
|  |         wifi_ap_max_conn = 8; | ||||||
| 
 | 
 | ||||||
|         int32_t wifi_ap_beacon_interval = 100; |         int32_t wifi_ap_beacon_interval = 100; | ||||||
|         sysparam_get_int32("wifi_ap_beacon_interval", &wifi_ap_beacon_interval); |         sysparam_get_int32("wifi_ap_beacon_interval", &wifi_ap_beacon_interval); | ||||||
|  | @ -357,5 +361,6 @@ extern "C" void wifi_task(void *pvParameters) { | ||||||
|     xSemaphoreGive(wifi_available_semaphore); |     xSemaphoreGive(wifi_available_semaphore); | ||||||
| 
 | 
 | ||||||
|     //monitor loop connection here
 |     //monitor loop connection here
 | ||||||
|  |     printf("wifi task done\n"); | ||||||
|     vTaskDelete(nullptr); |     vTaskDelete(nullptr); | ||||||
| } | } | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 7faa16b07ce0d606f9525a316990da5b58e61314 | Subproject commit a8217311e0d8547127b69b7c4ead62ed3aa87b79 | ||||||
							
								
								
									
										4
									
								
								pcb/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								pcb/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -31,8 +31,6 @@ fp-info-cache | ||||||
| *.wrl | *.wrl | ||||||
| *.step | *.step | ||||||
| 
 | 
 | ||||||
| *-backups/ | *-bak | ||||||
| gen/ | gen/ | ||||||
| pcb.zip | pcb.zip | ||||||
| 
 |  | ||||||
| report.txt |  | ||||||
							
								
								
									
										3
									
								
								webapp/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								webapp/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +0,0 @@ | ||||||
| node_modules/ |  | ||||||
| src/gen/ |  | ||||||
| package-lock.json |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue