├── user_config.h ├── testpicture.ppm ├── universalbridge.pdf ├── display_lcd.h ├── queue.c ├── http.h ├── application.h ├── i2s.h ├── README.md ├── display_spitft.h ├── display_ssd1306.h ├── rboot-config.c ├── display_orbital.h ├── display_eastrising.h ├── display_cfa634.h ├── .gitignore ├── init.h ├── remote_trigger.h ├── io_aux.h ├── io_pcf.h ├── io_ledpixel.h ├── .gitmodules ├── font.h ├── sys_time.h ├── io_mcp.h ├── queue.h ├── eastrising_upload_picture ├── sequencer.h ├── io_ledpixel_i2s.h ├── io_ledpixel_uart.h ├── attribute.h ├── wlan.h ├── esp8266_memory_map ├── third-party └── lwip-espressif-contributed │ ├── include │ ├── puck_def.h │ ├── espconn_buf.h │ ├── sntp.h │ ├── ping.h │ ├── time.h │ ├── espconn_tcp.h │ ├── dhcpserver.h │ ├── espconn_udp.h │ └── mdns.h │ ├── Makefile │ ├── espconn_mdns.c │ ├── espconn_buf.c │ ├── netio.c │ └── ping.c ├── lwipopts.h ├── font └── Makefile ├── flashmap ├── crosstool-config.patch ├── dispatch.h ├── uart.h ├── display.h ├── rboot-interface.h ├── spi.h ├── ota.h ├── io_gpio.h ├── lwip-interface.h ├── resetserial.cpp ├── i2c.h ├── config.h ├── init.c ├── i2c_sensor.h ├── stats.h ├── remote_trigger.c ├── symboltable.pl ├── io_aux.c ├── i2s.c ├── font.c ├── rboot-interface.c ├── io_pcf.c ├── io.h ├── io_ledpixel.c ├── sequencer.c └── display_cfa634.c /user_config.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testpicture.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eriksl/esp8266-universal-io-bridge/HEAD/testpicture.ppm -------------------------------------------------------------------------------- /universalbridge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eriksl/esp8266-universal-io-bridge/HEAD/universalbridge.pdf -------------------------------------------------------------------------------- /display_lcd.h: -------------------------------------------------------------------------------- 1 | #ifndef display_lcd_h 2 | #define display_lcd_h 3 | 4 | #include "display.h" 5 | 6 | extern display_hooks_t display_hooks_lcd; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /queue.c: -------------------------------------------------------------------------------- 1 | #include "queue.h" 2 | 3 | void queue_new(queue_t *queue, int size, char *buffer) 4 | { 5 | queue->data = buffer; 6 | queue->size = size; 7 | queue->in = 0; 8 | queue->out = 0; 9 | } 10 | -------------------------------------------------------------------------------- /http.h: -------------------------------------------------------------------------------- 1 | #ifndef http_h 2 | #define http_h 3 | 4 | #include "util.h" 5 | #include "application.h" 6 | #include "dispatch.h" 7 | 8 | app_action_t application_function_http_get(app_params_t *); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /application.h: -------------------------------------------------------------------------------- 1 | #ifndef application_h 2 | #define application_h 3 | 4 | #include 5 | #include 6 | 7 | void application_init(void); 8 | app_action_t application_content(app_params_t *); 9 | #endif 10 | -------------------------------------------------------------------------------- /i2s.h: -------------------------------------------------------------------------------- 1 | #ifndef __i2s_h__ 2 | #define __i2s_h__ 3 | 4 | #include 5 | #include 6 | 7 | bool i2s_init(void); 8 | bool i2s_send(unsigned int length, const uint8_t *data); 9 | void i2s_flush(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266 universal I/O bridge 2 | 3 | Please refer to the documentation in PDF (recommended) format: http://github.com/eriksl/esp8266-universal-io-bridge/blob/master/universalbridge.pdf 4 | or in HTML format: http://github.com/eriksl/esp8266-universal-io-bridge/blob/master/universalbridge.html. 5 | -------------------------------------------------------------------------------- /display_spitft.h: -------------------------------------------------------------------------------- 1 | #ifndef display_spitft_h 2 | #define display_spitft_h 3 | 4 | #include "display.h" 5 | 6 | extern display_hooks_t display_hooks_spitft; 7 | extern const char help_description_display_spitft[]; 8 | 9 | app_action_t application_function_display_spitft(app_params_t *); 10 | #endif 11 | -------------------------------------------------------------------------------- /display_ssd1306.h: -------------------------------------------------------------------------------- 1 | #ifndef display_ssd1306_h 2 | #define display_ssd1306_h 3 | 4 | #include "display.h" 5 | 6 | extern const char help_description_display_ssd1306[]; 7 | extern const display_hooks_t display_hooks_ssd1306; 8 | 9 | app_action_t application_function_display_ssd1306(app_params_t *); 10 | #endif 11 | -------------------------------------------------------------------------------- /rboot-config.c: -------------------------------------------------------------------------------- 1 | #include "rboot-interface.h" 2 | 3 | const rboot_if_config_t config = 4 | { 5 | .magic = rboot_if_conf_magic, 6 | .version = rboot_if_conf_version, 7 | .boot_mode = rboot_if_conf_mode_standard, 8 | .slot_current = 0, 9 | .slot_count = 2, 10 | .slots = { 0x02000, 0x102000, 0x00000, 0x00000 } 11 | }; 12 | -------------------------------------------------------------------------------- /display_orbital.h: -------------------------------------------------------------------------------- 1 | #ifndef display_orbital_h 2 | #define display_orbital_h 3 | 4 | #include "display.h" 5 | #include "dispatch.h" 6 | 7 | extern const char help_description_display_orbital[]; 8 | app_action_t application_function_display_orbital(app_params_t *); 9 | 10 | extern display_hooks_t display_hooks_orbital; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /display_eastrising.h: -------------------------------------------------------------------------------- 1 | #ifndef display_eastrising_h 2 | #define display_eastrising_h 3 | 4 | #include "display.h" 5 | #include "dispatch.h" 6 | 7 | extern const char help_description_display_eastrising[]; 8 | extern const display_hooks_t display_hooks_eastrising; 9 | 10 | app_action_t application_function_display_eastrising(app_params_t *); 11 | #endif 12 | -------------------------------------------------------------------------------- /display_cfa634.h: -------------------------------------------------------------------------------- 1 | #ifndef display_cfa634_h 2 | #define display_cfa634_h 3 | 4 | #include "display.h" 5 | 6 | bool display_cfa634_setup(unsigned int io, unsigned int pin); 7 | 8 | extern const char help_description_display_cfa634[]; 9 | app_action_t application_function_display_cfa634(app_params_t *); 10 | 11 | extern display_hooks_t display_hooks_cfa; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.h.gch 3 | *.bin 4 | *.elf 5 | *.a 6 | .*.swp 7 | /doc 8 | /linkmap 9 | /t 10 | /session 11 | /test* 12 | /loadscript 13 | /otapush 14 | /espflash 15 | /espif 16 | /universalbridge.odt 17 | /demo 18 | /dump 19 | /espplay 20 | /font/bdf2c 21 | /font/font_32x16.c 22 | /font/t 23 | /furelise 24 | /listsymbols.pl 25 | /oxygene 26 | /pins 27 | /resetserial 28 | /t.c 29 | /t.pl 30 | /tmp 31 | -------------------------------------------------------------------------------- /init.h: -------------------------------------------------------------------------------- 1 | #ifndef _init_h_ 2 | #define _init_h_ 3 | 4 | #include "util.h" 5 | 6 | #include 7 | 8 | enum 9 | { 10 | stack_paint_magic = 0xabcdefaa, 11 | stack_top = 0x3fffeb30, 12 | stack_bottom = 0x40000000 - sizeof(void *) 13 | }; 14 | 15 | extern volatile uint32_t *stack_stack_sp_initial; 16 | extern int stack_stack_painted; 17 | 18 | void stack_paint_stack(void); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /remote_trigger.h: -------------------------------------------------------------------------------- 1 | #ifndef _remote_trigger_h_ 2 | #define _remote_trigger_h_ 3 | 4 | #include 5 | 6 | #include "dispatch.h" 7 | 8 | bool remote_trigger_init(void); 9 | app_action_t application_function_trigger_remote(app_params_t *); 10 | bool remote_trigger_add(unsigned int index, unsigned int io, unsigned int pin, io_trigger_t); 11 | void remote_trigger_send(unsigned int argument); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /io_aux.h: -------------------------------------------------------------------------------- 1 | #ifndef io_aux_h 2 | #define io_aux_h 3 | 4 | #include "io.h" 5 | #include "util.h" 6 | 7 | #include 8 | 9 | typedef enum 10 | { 11 | io_aux_pin_gpio = 0, 12 | io_aux_pin_adc, 13 | io_aux_pin_error, 14 | io_aux_pin_size = io_aux_pin_error 15 | } io_aux_pin_t; 16 | 17 | assert_size(io_aux_pin_t, 4); 18 | 19 | extern const io_info_entry_t io_info_entry_aux; 20 | 21 | void io_aux_pins_changed(uint32_t pin_status_mask, uint16_t pin_value_mask); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /io_pcf.h: -------------------------------------------------------------------------------- 1 | #ifndef io_pcf_h 2 | #define io_pcf_h 3 | 4 | #include "util.h" 5 | #include "io.h" 6 | 7 | #include 8 | 9 | typedef enum 10 | { 11 | io_pcf_instance_3a = 0, 12 | io_pcf_instance_26, 13 | io_pcf_instance_size 14 | } io_pcf_instance_t; 15 | 16 | enum 17 | { 18 | io_pcf_pin_size = 8, 19 | }; 20 | 21 | extern const io_info_entry_t io_info_entry_pcf_3a; 22 | extern const io_info_entry_t io_info_entry_pcf_26; 23 | 24 | void io_pcf_pins_changed(uint32_t pin_status_mask, uint16_t pin_value_mask, uint8_t io); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /io_ledpixel.h: -------------------------------------------------------------------------------- 1 | #ifndef io_ledpixel_h 2 | #define io_ledpixel_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef enum 9 | { 10 | ledpixel_invalid, 11 | ledpixel_uart_0, 12 | ledpixel_uart_1, 13 | ledpixel_i2s 14 | } io_ledpixel_mode_t; 15 | 16 | extern const io_info_entry_t io_info_entry_ledpixel; 17 | 18 | io_error_t io_ledpixel_pinmask(unsigned int mask); 19 | io_ledpixel_mode_t io_ledpixel_mode(unsigned int io, unsigned int pin); 20 | bool io_ledpixel_pre_init(unsigned int io, unsigned int pin); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third-party/ESP8266_NONOS_SDK"] 2 | path = third-party/ESP8266_NONOS_SDK 3 | url = https://github.com/espressif/ESP8266_NONOS_SDK 4 | [submodule "third-party/crosstool-ng"] 5 | path = third-party/crosstool-ng 6 | url = https://github.com/eriksl/crosstool-NG.git 7 | [submodule "third-party/lwip-for-esp8266-nonos-sdk"] 8 | path = third-party/lwip-for-esp8266-nonos-sdk 9 | url = http://github.com/eriksl/lwip-for-esp8266-nonos-sdk 10 | [submodule "third-party/esptool2"] 11 | path = third-party/esptool2 12 | url = http://github.com/raburton/esptool2 13 | [submodule "third-party/rboot"] 14 | path = third-party/rboot 15 | url = http://github.com/raburton/rboot 16 | -------------------------------------------------------------------------------- /font.h: -------------------------------------------------------------------------------- 1 | #ifndef _font_h_ 2 | #define _font_h_ 3 | 4 | #include "dispatch.h" 5 | 6 | #include 7 | 8 | typedef enum 9 | { 10 | font_cell_height = 32, 11 | font_cell_width = 32, 12 | } font_enum_t; 13 | 14 | typedef struct 15 | { 16 | unsigned int width; 17 | unsigned int height; 18 | } font_info_t; 19 | 20 | typedef uint8_t font_cell_t[font_cell_height][font_cell_width]; 21 | 22 | assert_size(font_cell_t, 1024); 23 | 24 | void font_init(void); 25 | bool font_select(bool logging); 26 | bool font_get_info(font_info_t *); 27 | bool font_render(unsigned int code, font_cell_t cell); 28 | 29 | extern const char help_description_display_font_select[]; 30 | app_action_t application_function_display_font_select(app_params_t *); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /sys_time.h: -------------------------------------------------------------------------------- 1 | #ifndef _sys_time_h_ 2 | #define _sys_time_h_ 3 | 4 | #include "util.h" 5 | #include "attribute.h" 6 | 7 | #include 8 | #include 9 | 10 | void time_init(void); 11 | void time_periodic(void); 12 | void time_sntp_start(void); 13 | void time_stats(string_t *); 14 | 15 | void time_set_hms(unsigned int h, unsigned int m, unsigned int s); 16 | void time_set_stamp(uint64_t base); 17 | bool time_set_timezone(int tz, string_t *errormsg); 18 | int time_get_timezone(void); 19 | const char *time_get(unsigned int *h, unsigned int *m, unsigned int *s, 20 | unsigned int *Y, unsigned int *M, unsigned int *D); 21 | uint64_t time_get_us(void); 22 | bool time_sntp_get_server(ip_addr_t *server); 23 | bool time_sntp_set_server(string_t *errormsg, ip_addr_t server); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /io_mcp.h: -------------------------------------------------------------------------------- 1 | #ifndef io_mcp_h 2 | #define io_mcp_h 3 | 4 | #include "io.h" 5 | #include "util.h" 6 | 7 | #include 8 | 9 | enum 10 | { 11 | io_mcp_pin_size = 16, 12 | }; 13 | 14 | typedef enum 15 | { 16 | io_mcp_instance_20 = 0, 17 | io_mcp_instance_21, 18 | io_mcp_instance_22, 19 | io_mcp_instance_spi, 20 | io_mcp_instance_size 21 | } io_mcp_instance_t; 22 | 23 | extern const io_info_entry_t io_info_entry_mcp_20; 24 | extern const io_info_entry_t io_info_entry_mcp_21; 25 | extern const io_info_entry_t io_info_entry_mcp_22; 26 | extern const io_info_entry_t io_info_entry_mcp_spi; 27 | 28 | void io_mcp_pins_changed(uint32_t pin_status_mask, uint16_t pin_value_mask, uint8_t id); 29 | 30 | extern const char help_description_io_mcp_spi[]; 31 | app_action_t application_function_io_mcp_spi(app_params_t *parameters); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /queue.h: -------------------------------------------------------------------------------- 1 | #ifndef queue_h 2 | #define queue_h 3 | 4 | #include 5 | 6 | #include "util.h" 7 | 8 | typedef struct 9 | { 10 | char *data; 11 | int size; 12 | int in; 13 | int out; 14 | } queue_t; 15 | 16 | void queue_new(queue_t *queue, int size, char *buffer); 17 | 18 | attr_inline attr_pure char queue_empty(const queue_t *queue) 19 | { 20 | return(queue->in == queue->out); 21 | } 22 | 23 | attr_inline attr_pure char queue_full(const queue_t *queue) 24 | { 25 | return(((queue->in + 1) % queue->size) == queue->out); 26 | } 27 | 28 | attr_inline void queue_flush(queue_t *queue) 29 | { 30 | queue->in = 0; 31 | queue->out = 0; 32 | } 33 | 34 | attr_inline void queue_push(queue_t *queue, char data) 35 | { 36 | queue->data[queue->in] = data; 37 | queue->in = (queue->in + 1) % queue->size; 38 | } 39 | 40 | attr_inline char queue_pop(queue_t *queue) 41 | { 42 | char data; 43 | 44 | data = queue->data[queue->out]; 45 | queue->out = (queue->out + 1) % queue->size; 46 | 47 | return(data); 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /eastrising_upload_picture: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ####################################################################################### 4 | # convert and upload (flash) random picture to ESP with Eastrising colour TFT display # 5 | # for now only Eastrising display, also only slot #0. # 6 | # it uses ImageMagick ("convert") for the conversion. # 7 | ####################################################################################### 8 | 9 | if [ $# != 3 ]; then 10 | echo "usage: $0: " 11 | exit 1 12 | fi 13 | 14 | case $2 in 15 | 0) 16 | offset=0x200000 17 | ;; 18 | 1) 19 | offset=0x280000 20 | ;; 21 | *) 22 | echo "$0: use slot 0 or slot 1" 23 | exit 1 24 | ;; 25 | esac 26 | 27 | tmpfile="$(mktemp --suffix=.ppm)" 28 | 29 | trap 'rm -f "$tmpfile"' 0 30 | 31 | convert -resize '480x272!' -gamma 0.6 -depth 8 "$3" "ppm:$tmpfile" 32 | espflash --write --host "$1" --start $offset --file "$tmpfile" 33 | espflash --verify --host "$1" --start $offset --file "$tmpfile" 34 | -------------------------------------------------------------------------------- /sequencer.h: -------------------------------------------------------------------------------- 1 | #ifndef _sequencer_h_ 2 | #define _sequencer_h_ 3 | 4 | #include "attribute.h" 5 | #include "util.h" 6 | 7 | #include 8 | #include 9 | 10 | int sequencer_get_current(void); 11 | int sequencer_get_start(void); 12 | uint64_t sequencer_get_current_end_time(void); 13 | int sequencer_get_repeats(void); 14 | void sequencer_get_status(bool *running, unsigned int *start, unsigned int *flash_size, unsigned int *flash_size_entries, 15 | unsigned int *flash_offset_flash0, unsigned int *flash_offset_flash1, unsigned int *flash_offset_mapped); 16 | void sequencer_run(void); 17 | void sequencer_init(void); 18 | bool sequencer_clear(void); 19 | void sequencer_start(unsigned int start, unsigned int repeats); 20 | void sequencer_stop(void); 21 | bool sequencer_set_entry(unsigned int entry, int io, int pin, uint32_t value, int duration); 22 | bool sequencer_get_entry(unsigned int entry, bool *active, int *io, int *pin, unsigned int *value, unsigned int *duration); 23 | bool sequencer_remove_entry(unsigned int entry); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /io_ledpixel_i2s.h: -------------------------------------------------------------------------------- 1 | #ifndef io_ledpixel_i2s_h 2 | #define io_ledpixel_i2s_h 3 | 4 | #include "io.h" 5 | #include "util.h" 6 | 7 | #include 8 | #include 9 | 10 | bool io_ledpixel_i2s_pre_init(unsigned int io, unsigned int pin); 11 | io_error_t io_ledpixel_i2s_init(const struct io_info_entry_T *); 12 | void io_ledpixel_i2s_post_init(const struct io_info_entry_T *); 13 | unsigned int io_ledpixel_i2s_pin_max_value(const struct io_info_entry_T *info, io_data_pin_entry_t *data, const io_config_pin_entry_t *pin_config, unsigned int pin); 14 | io_error_t io_ledpixel_i2s_init_pin_mode(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin); 15 | io_error_t io_ledpixel_i2s_read_pin(string_t *, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int, unsigned int *); 16 | io_error_t io_ledpixel_i2s_write_pin(string_t *, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int, unsigned int); 17 | io_error_t io_ledpixel_i2s_pinmask(unsigned int mask); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /io_ledpixel_uart.h: -------------------------------------------------------------------------------- 1 | #ifndef io_ledpixel_uart_h 2 | #define io_ledpixel_uart_h 3 | 4 | #include "io.h" 5 | #include "util.h" 6 | 7 | #include 8 | #include 9 | 10 | bool io_ledpixel_uart_pre_init(unsigned int io, unsigned int pin); 11 | io_error_t io_ledpixel_uart_init(const struct io_info_entry_T *); 12 | void io_ledpixel_uart_post_init(const struct io_info_entry_T *); 13 | unsigned int io_ledpixel_uart_pin_max_value(const struct io_info_entry_T *info, io_data_pin_entry_t *data, const io_config_pin_entry_t *pin_config, unsigned int pin); 14 | io_error_t io_ledpixel_uart_init_pin_mode(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin); 15 | io_error_t io_ledpixel_uart_read_pin(string_t *, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int, unsigned int *); 16 | io_error_t io_ledpixel_uart_write_pin(string_t *, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int, unsigned int); 17 | io_error_t io_ledpixel_uart_pinmask(unsigned int mask); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /attribute.h: -------------------------------------------------------------------------------- 1 | #ifndef attribute_h 2 | #define attribute_h 3 | 4 | #define iram __attribute__((section(".iram.text"))) __attribute__ ((optimize("Os"))) 5 | #define roflash __attribute__((section(".flash.rodata"))) 6 | #define attr_flash_align __attribute__((aligned(4))) 7 | #define attr_align_int __attribute__((aligned(sizeof(int)))) 8 | #define attr_inline inline __attribute__((always_inline)) __attribute__((flatten)) static 9 | #define attr_unused __attribute__ ((unused)) 10 | #define attr_used __attribute__ ((used)) 11 | #define attr_pure __attribute__ ((pure)) 12 | #define attr_const __attribute__ ((const)) 13 | #define attr_packed __attribute__ ((__packed__)) 14 | #define attr_nonnull __attribute__ ((nonnull)) 15 | #define attr_result_used __attribute__ ((warn_unused_result)) 16 | #define assert_size(type, size) _Static_assert(sizeof(type) == size, "sizeof(" #type ") != " #size) 17 | #define assert_size_le(type1, type2) _Static_assert(sizeof(type1) <= sizeof(type2), "sizeof(" #type1 ") > sizeof(" #type2 ")") 18 | #define assert_enum(name, value) _Static_assert((name) == (value), "enum value for " #name " != " #value) 19 | #define assert_field(name, field, offset) _Static_assert(offsetof(name, field) == offset) 20 | #endif 21 | -------------------------------------------------------------------------------- /wlan.h: -------------------------------------------------------------------------------- 1 | #ifndef _wlan_h_ 2 | #define _wlan_h_ 3 | 4 | #include "util.h" 5 | #include "dispatch.h" 6 | 7 | #include 8 | 9 | typedef enum 10 | { 11 | config_wlan_mode_client, 12 | config_wlan_mode_ap 13 | } config_wlan_mode_t; 14 | 15 | extern roflash const char help_description_stats_wlan[]; 16 | extern roflash const char help_description_wlan_ap_config[]; 17 | extern roflash const char help_description_wlan_client_config[]; 18 | extern roflash const char help_description_wlan_mode[]; 19 | extern roflash const char help_description_wlan_scan[]; 20 | 21 | void wlan_init(void); 22 | bool wlan_reconnect(void); 23 | void wlan_periodic(void); 24 | void wlan_start_recovery(void); 25 | void wlan_multicast_init_groups(void); 26 | bool wlan_client_configure(string_t *error, const char *ssid, const char *password); 27 | void stats_wlan(string_t *dst); 28 | 29 | app_action_t application_function_wlan_scan(app_params_t *parameters); 30 | app_action_t application_function_wlan_ap_configure(app_params_t *parameters); 31 | app_action_t application_function_wlan_client_configure(app_params_t *parameters); 32 | app_action_t application_function_stats_wlan(app_params_t *parameters); 33 | app_action_t application_function_wlan_mode(app_params_t *parameters); 34 | app_action_t application_function_wlan_reset(app_params_t *parameters); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /esp8266_memory_map: -------------------------------------------------------------------------------- 1 | esp8266 memory map flash memory map (start from 40100000) 2 | 3 | segment size sub size start size start 4 | - 700.00000 5 | - 600.02000 I/O 6 | - 600.01800 I/O 7 | - 600.01000 I/O 8 | - 600.00000 I/O 9 | - 403.00000 10 | irom0 402.10000 11 | SPI-MAPPED 402.00000 <--- 10000 irom0 12 | - 401.40000 13 | - 401.10000 14 | icache1 4000 401.0c000 4000 0c000 cache / "dummy when writing composite image" 15 | icache0 4000 401.08000 4000 08000 cache / "dummy when writing composite image" 16 | iram1 8000 401.00000 <--- 8000 00000 iram0 17 | - 400.10000 18 | brom 10000 400.00000 stack bottom 19 | - 14cc 5324 3ff.feb34 stack top (grows downwards) 20 | - 8 8 3ff.feb2c "system data ram #3" 21 | - b2c 2860 3ff.fe000 ram free to use #1 (apparently, tested) 22 | 190c 6412 3ff.fc6f4 "system data ram #2" 23 | 33c 828 3ff.fc3b8 ram free to use #2 (untested) 24 | - 3b8 952 3ff.fc000 "system data ram #1" 25 | dram0 18000 14000 3ff.e8000 bss, rodata, data, system heap 26 | - 3ff.e0000 27 | - 20000 3ff.c0000 28 | - 3ff.30000 29 | - 3ff.20000 30 | - 3ff.00010 31 | dport0 10 3ff.00000 32 | - 200.00000 33 | - 000.00000 34 | 35 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/puck_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * puck_def.h 3 | * 4 | * Created on: Jul 22, 2010 5 | * Author: dtoma 6 | */ 7 | 8 | #ifndef PUCK_DEF_H_ 9 | #define PUCK_DEF_H_ 10 | 11 | 12 | 13 | #define INSTRUMENT_PORT 8760 14 | 15 | #define INSTRUMENT_LENGTH 80 16 | 17 | #define MDNS_NAME_LENGTH 68 //68 18 | 19 | char* PUCK_SERVICE = NULL; 20 | //#define PUCK_SERVICE "_Escpressif._tcp.local" 21 | #define DNS_SD_SERVICE "_services._dns-sd._udp.local" 22 | #define SERVICE_DESCRIPTION "PUCK PROTOCOL" 23 | #define PUCK_SERVICE_LENGTH 30 24 | 25 | #define UUID_LEN 16 26 | #define DS_VERS_LEN 2 27 | #define DS_SIZE_LEN 2 28 | #define MAN_ID_LEN 4 29 | #define MAN_MODEL_LEN 2 30 | #define MAN_VERS_LEN 2 31 | #define SER_NUM_LEN 4 32 | #define NAME_LEN 64 33 | #define PUCK_DATASHEET_SIZE 96 34 | 35 | #define UUID_OFFSET 0 36 | #define DS_VERS_OFFSET UUID_LEN + UUID_OFFSET 37 | #define DS_SIZE_OFFSET DS_VERS_LEN + DS_VERS_OFFSET 38 | #define MAN_ID_OFFSET DS_SIZE_LEN + DS_SIZE_OFFSET 39 | #define MAN_MODEL_OFFSET MAN_ID_LEN + MAN_ID_OFFSET 40 | #define MAN_VERS_OFFSET MAN_MODEL_LEN + MAN_MODEL_OFFSET 41 | #define SER_NUM_OFFSET MAN_VERS_LEN + MAN_VERS_OFFSET 42 | #define NAME_OFFSET SER_NUM_LEN + SER_NUM_OFFSET 43 | 44 | #endif /* __PUCK_DEF_H__ */ 45 | -------------------------------------------------------------------------------- /lwipopts.h: -------------------------------------------------------------------------------- 1 | // lwip core 2 | 3 | #define MEM_SIZE (9 * 1024) 4 | #define MEMP_NUM_PBUF 8 5 | #define MEMP_NUM_UDP_PCB 4 6 | #define MEMP_NUM_TCP_PCB 2 7 | #define MEMP_NUM_TCP_PCB_LISTEN 2 8 | #define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN 9 | #define MEMP_NUM_REASSDATA 1 10 | #define MEMP_NUM_FRAG_PBUF 0 11 | #define MEMP_NUM_ARP_QUEUE 0 12 | #define MEMP_NUM_IGMP_GROUP 10 13 | #define ARP_TABLE_SIZE 2 14 | #define ARP_QUEUEING 0 15 | #define ETHARP_TRUST_IP_MAC 1 16 | #define IP_REASSEMBLY 1 17 | #define IP_FRAG 1 18 | #define IP_DEFAULT_TTL 128 19 | #define IP_SOF_BROADCAST 0 20 | #define IP_SOF_BROADCAST_RECV 0 21 | #define LWIP_BROADCAST_PING 1 22 | #define LWIP_MULTICAST_PING 1 23 | #define LWIP_RAW 0 24 | #define LWIP_DHCP 1 25 | #define LWIP_IGMP 1 26 | #define LWIP_DNS 0 27 | #define DHCP_DOES_ARP_CHECK 0 28 | #define TCP_QUEUE_OOSEQ 0 29 | #define TCP_MSS 1460 30 | #define TCP_WND (2 * TCP_MSS) 31 | #define TCP_SND_BUF (4 * TCP_MSS) 32 | #define TCP_SND_QUEUELEN (4 * TCP_SND_BUF / TCP_MSS) 33 | #define TCP_SNDLOWAT 1 34 | #define TCP_SNDQUEUELOWAT (TCP_SND_QUEUELEN - 1) 35 | #define TCP_OVERSIZE TCP_MSS 36 | #define TCP_MAXRTX 2 37 | #define PBUF_POOL_SIZE 2 38 | #define LWIP_NETIF_HOSTNAME 1 39 | #define LWIP_NETCONN 0 40 | #define LWIP_SOCKET 0 41 | #define LWIP_TCP_KEEPALIVE 0 42 | #define LWIP_TCP_TIMESTAMPS 0 43 | #define LWIP_STATS 0 44 | #define LWIP_WND_SCALE 0 45 | 46 | // lwip contributed code 47 | #define DHCP_MAXRTX 4 48 | #define LWIP_MDNS 0 49 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/espconn_buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ringbuf.h 3 | * 4 | * Created on: Apr 22, 2016 5 | * Author: liuhan 6 | */ 7 | 8 | #ifndef _ESPCONN_BUF_H_ 9 | #define _ESPCONN_BUF_H_ 10 | 11 | /* 12 | * ringbuffer.c 13 | * 14 | * Created on: Apr 22, 2016 15 | * Author: liuhan 16 | */ 17 | #include "stdint.h" 18 | 19 | #include "ets_sys.h" 20 | #include "os_type.h" 21 | 22 | typedef struct ringbuf_t { 23 | uint8_t *buf; 24 | uint8_t *head, *tail; 25 | size_t size; 26 | } ringbuf, *ringbuf_t; 27 | 28 | ringbuf_t ringbuf_new(size_t capacity); 29 | 30 | size_t ringbuf_buffer_size(const struct ringbuf_t *rb); 31 | 32 | void ringbuf_reset(ringbuf_t rb); 33 | 34 | void ringbuf_free(ringbuf_t *rb); 35 | 36 | size_t ringbuf_capacity(const struct ringbuf_t *rb); 37 | 38 | size_t ringbuf_bytes_free(const struct ringbuf_t *rb); 39 | 40 | size_t ringbuf_bytes_used(const struct ringbuf_t *rb); 41 | 42 | int ringbuf_is_full(const struct ringbuf_t *rb); 43 | 44 | int ringbuf_is_empty(const struct ringbuf_t *rb); 45 | 46 | const void* ringbuf_tail(const struct ringbuf_t *rb); 47 | 48 | const void* ringbuf_head(const struct ringbuf_t *rb); 49 | 50 | static uint8_t *ringbuf_nextp(ringbuf_t rb, const uint8_t *p); 51 | 52 | size_t ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset); 53 | 54 | size_t ringbuf_memset(ringbuf_t dst, int c, size_t len); 55 | 56 | void *ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count); 57 | 58 | void *ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count); 59 | 60 | #endif /* RINGBUF_H_ */ 61 | -------------------------------------------------------------------------------- /font/Makefile: -------------------------------------------------------------------------------- 1 | # generate bitmap fonts for graphical displays 2 | 3 | HOST = esp1 4 | BIN = fonts.bin 5 | BDF2C = bdf2c 6 | FONT_5x8 = spleen-5x8.bdf 7 | FONT_6x12 = ter-u12b.bdf 8 | FONT_8x14 = ter-u14b.bdf 9 | FONT_10x18 = ter-u18b.bdf 10 | FONT_12x24 = ter-u24b.bdf 11 | FONT_14x28 = ter-u28b.bdf 12 | FONT_16x32 = ter-u32b.bdf 13 | FONTS = $(FONT_5x8) $(FONT_6x12) $(FONT_8x14) $(FONT_10x18) $(FONT_12x24) $(FONT_14x28) $(FONT_16x32) 14 | FONT_CODE_RANGE = 32-126,160-165,169,171,173-174,176,181,187,191,223-252,913-939,945-981,8211,8212,8224-8226,8364,8482,8486,9834-9835,57344-57347 15 | 16 | MAKEFLAGS += --no-builtin-rules 17 | 18 | .PRECIOUS: bdf2c.c Makefile 19 | .PHONY: always 20 | 21 | all: $(BIN) 22 | 23 | $(BIN): $(BDF2C) $(FONTS) 24 | $(BDF2C) $(BIN) $(FONT_CODE_RANGE) \ 25 | $(FONT_5x8) 5 8 8 3 0 0 \ 26 | $(FONT_6x12) 6 12 8 2 0 0 \ 27 | $(FONT_8x14) 8 14 8 1 0 0 \ 28 | $(FONT_10x18) 10 18 0 6 0 0 \ 29 | $(FONT_12x24) 12 24 0 4 1 0 \ 30 | $(FONT_14x28) 14 28 0 2 1 0 \ 31 | $(FONT_16x32) 16 32 0 0 2 0 \ 32 | 33 | flash: $(BIN) 34 | @if [ `stat --format=%s $(BIN)` -gt 196608 ]; then echo "*** font image too large ***"; exit 1; fi 35 | espif --host $(HOST) --filename $(BIN) --start 0x0c6 --write 36 | espif --host $(HOST) --filename $(BIN) --start 0x1c6 --write 37 | espif --host $(HOST) --filename $(BIN) --start 0x0c6 --verify 38 | espif --host $(HOST) --filename $(BIN) --start 0x1c6 --verify 39 | 40 | $(BDF2C): $(BDF2C).c 41 | gcc -Wall -Werror -O3 -s $< -o $@ 42 | 43 | clean: 44 | rm -f $(BDF2C) $(BIN) 45 | -------------------------------------------------------------------------------- /flashmap: -------------------------------------------------------------------------------- 1 | * OTA (2 Mbyte, 16 Mbit, 2 identical slots) 2 | 3 | 1fd000-1fffff 03000 3 default system parameter values SYSTEM_PARTITION_SYSTEM_PARAMETER blank.bin 4 | 1fc000-1fcfff 01000 1 default RF parameter values SYSTEM_PARTITION_PHY_DATA default.bin 5 | 1fb000-1fbfff 01000 1 unused (mirror 0fb000) 6 | 1fa000-1fafff 01000 1 unused (mirror 0fa000) 7 | 1f6000-1f9fff 04000 4 sequencer storage mirror #1 SYSTEM_PARTITION_CUSTOMER_BEGIN+6 8 | 1c6000-1f5fff 30000 48 font storage mirror #1 SYSTEM_PARTITION_CUSTOMER_BEGIN+10 9 | 102000-1c5fff c4000 196 ota image slot #1 SYSTEM_PARTITION_CUSTOMER_BEGIN+4 10 | 101000-101fff 01000 1 unused (mirror 001000) 11 | 100000-100fff 01000 1 unused (mirror 000000) 12 | 13 | 0fd000-0fffff 03000 3 unused (mirror 1fd000) 14 | 0fc000-0fcfff 01000 1 unused (mirror 1fc000) 15 | 0fb000-0fbfff 01000 1 RF calibration storage SYSTEM_PARTITION_RF_CAL 16 | 0fa000-0fafff 01000 1 user config SYSTEM_PARTITION_CUSTOMER_BEGIN+0 17 | 0f6000-0f9fff 04000 4 sequencer storage mirror #0 SYSTEM_PARTITION_CUSTOMER_BEGIN+5 18 | 0c6000-0f5fff 30000 48 font storage mirror #0 SYSTEM_PARTITION_CUSTOMER_BEGIN+9 19 | 002000-0c5fff c4000 196 ota image slot #0 SYSTEM_PARTITION_CUSTOMER_BEGIN+3 20 | 001000-001fff 01000 1 rboot config SYSTEM_PARTITION_CUSTOMER_BEGIN+2 21 | 000000-000fff 01000 1 rboot ota boot SYSTEM_PARTITION_CUSTOMER_BEGIN+1 22 | 23 | * OTA+ (4 Mbyte, 32 Mbit, space of slot 3-4 can be used for data) 24 | 25 | 300000-3fffff 100000 256 not yet in use SYSTEM_PARTITION_CUSTOMER_BEGIN+11 26 | 280000-2fffff 80000 128 picture storage #1 SYSTEM_PARTITION_CUSTOMER_BEGIN+8 27 | 200000-27ffff 80000 128 picture storage #0 SYSTEM_PARTITION_CUSTOMER_BEGIN+7 28 | -------------------------------------------------------------------------------- /crosstool-config.patch: -------------------------------------------------------------------------------- 1 | --- crosstool.config 2021-04-29 12:35:01.042648997 +0200 2 | +++ crosstool.config 2021-04-29 12:41:31.550091088 +0200 3 | @@ -24,14 +24,18 @@ 4 | CT_XTENSA_CUSTOM=y 5 | CT_TARGET_USE_OVERLAY=y 6 | CT_TARGET_VENDOR="lx106" 7 | -CT_TARGET_CFLAGS="-mlongcalls" 8 | +CT_TARGET_CFLAGS="-mlongcalls -mno-target-align -mno-serialize-volatile" 9 | +CT_TARGET_LDFLAGS="-Wl,--size-opt" 10 | CT_OVERLAY_NAME="lx106" 11 | CT_OVERLAY_LOCATION="${CT_TOP_DIR}/overlays" 12 | CT_TOOLCHAIN_PKGVERSION="lx106" 13 | CT_NEWLIB_V_2_0=y 14 | CT_NEWLIB_VERSION="2.0.0" 15 | CT_LIBC_NEWLIB_V_2_0_0=y 16 | -CT_LIBC_NEWLIB_TARGET_CFLAGS="-DMALLOC_PROVIDED" 17 | +CT_LIBC_NEWLIB_TARGET_CFLAGS="-DMALLOC_PROVIDED -ffunction-sections -fdata-sections -Wl,--size-opt" 18 | +CT_LIBC_NEWLIB_IO_LL=y 19 | +CT_LIBC_NEWLIB_IO_FLOAT=y 20 | +CT_LIBC_NEWLIB_IO_LDBL=y 21 | CT_LIBC_NEWLIB_DISABLE_SUPPLIED_SYSCALLS=y 22 | # CT_LIBC_NEWLIB_FVWRITE_IN_STREAMIO is not set 23 | # CT_LIBC_NEWLIB_UNBUF_STREAM_OPT is not set 24 | @@ -40,7 +44,17 @@ 25 | CT_LIBC_NEWLIB_REENT_SMALL=y 26 | # CT_LIBC_NEWLIB_WIDE_ORIENT is not set 27 | # CT_LIBC_NEWLIB_LTO is not set 28 | # CT_CC_GCC_USE_GRAPHITE is not set 29 | CT_CC_GCC_DISABLE_PCH=y 30 | -CT_CC_LANG_CXX=y 31 | +CT_CC_GCC_LDBL_128=y 32 | +# CT_CC_LANG_CXX is not set 33 | +CT_CC_GCC_DEC_FLOATS_NO=y 34 | +CT_CC_GCC_DEC_FLOATS="no" 35 | +# CT_CC_GCC_DEC_FLOATS_AUTO is not set 36 | +# CT_CC_GCC_DEC_FLOATS_BID is not set 37 | +# CT_CC_GCC_DEC_FLOATS_DPD is not set 38 | # CT_COMP_LIBS_ISL is not set 39 | +CT_LOCAL_TARBALLS_DIR="${CT_TOP_DIR}/sources" 40 | +CT_PREFIX_DIR="${CT_TOP_DIR}/xtensa-lx106-elf" 41 | +# CT_INSTALL_LICENSES is not set 42 | +CT_DOWNLOAD_WGET_OPTIONS="--tries=3 -nc --progress=dot:binary" 43 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | 16 | GEN_LIBS = liblwipapp.a 17 | 18 | endif 19 | 20 | 21 | ############################################################# 22 | # Configuration i.e. compile options etc. 23 | # Target specific stuff (defines etc.) goes in here! 24 | # Generally values applying to a tree are captured in the 25 | # makefile at its root level - these are then overridden 26 | # for a subtree within the makefile rooted therein 27 | # 28 | #DEFINES += 29 | 30 | ############################################################# 31 | # Recursion Magic - Don't touch this!! 32 | # 33 | # Each subtree potentially has an include directory 34 | # corresponding to the common APIs applicable to modules 35 | # rooted at that subtree. Accordingly, the INCLUDE PATH 36 | # of a module can only contain the include directories up 37 | # its parent path, and not its siblings 38 | # 39 | # Required for each makefile to inherit from the parent 40 | # 41 | 42 | INCLUDES := $(INCLUDES) -I $(PDIR)include 43 | INCLUDES += -I ./ 44 | PDIR := ../$(PDIR) 45 | sinclude $(PDIR)Makefile 46 | 47 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/sntp.h: -------------------------------------------------------------------------------- 1 | #ifndef LWIP_SNTP_H 2 | #define LWIP_SNTP_H 3 | 4 | #include "lwip/opt.h" 5 | #include "lwip/ip_addr.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | typedef struct __tzrule_struct 16 | { 17 | char ch; 18 | int m; 19 | int n; 20 | int d; 21 | int s; 22 | time_t change; 23 | long offset; /* Match type of _timezone. */ 24 | } __tzrule_type; 25 | 26 | /** The maximum number of SNTP servers that can be set */ 27 | #ifndef SNTP_MAX_SERVERS 28 | #define SNTP_MAX_SERVERS 3 29 | #endif 30 | 31 | /** Set this to 1 to implement the callback function called by dhcp when 32 | * NTP servers are received. */ 33 | #ifndef SNTP_GET_SERVERS_FROM_DHCP 34 | #define SNTP_GET_SERVERS_FROM_DHCP 0//LWIP_DHCP_GET_NTP_SRV 35 | #endif 36 | 37 | /* Set this to 1 to support DNS names (or IP address strings) to set sntp servers */ 38 | #ifndef SNTP_SERVER_DNS 39 | #define SNTP_SERVER_DNS 1 40 | #endif 41 | 42 | bool sntp_get_timetype(void); 43 | void sntp_set_receive_time_size(void); 44 | /** One server address/name can be defined as default if SNTP_SERVER_DNS == 1: 45 | * #define SNTP_SERVER_ADDRESS "pool.ntp.org" 46 | */ 47 | 48 | #if SNTP_SERVER_DNS 49 | void sntp_setservername(u8_t idx, char *server); 50 | char *sntp_getservername(u8_t idx); 51 | #endif /* SNTP_SERVER_DNS */ 52 | 53 | #if SNTP_GET_SERVERS_FROM_DHCP 54 | void sntp_servermode_dhcp(int set_servers_from_dhcp); 55 | #else /* SNTP_GET_SERVERS_FROM_DHCP */ 56 | #define sntp_servermode_dhcp(x) 57 | #endif /* SNTP_GET_SERVERS_FROM_DHCP */ 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* LWIP_SNTP_H */ 64 | -------------------------------------------------------------------------------- /dispatch.h: -------------------------------------------------------------------------------- 1 | #ifndef dispatch_h 2 | #define dispatch_h 3 | 4 | #include "util.h" 5 | 6 | typedef enum 7 | { 8 | app_action_normal, 9 | app_action_error, 10 | app_action_empty, 11 | app_action_disconnect, 12 | app_action_http_ok, 13 | app_action_reset, 14 | } app_action_t; 15 | 16 | assert_size(app_action_t, 4); 17 | 18 | typedef enum 19 | { 20 | task_prio_low = 0, 21 | task_prio_medium, 22 | task_prio_high, 23 | task_prio_size, 24 | } task_prio_t; 25 | 26 | typedef enum 27 | { 28 | task_uart_fetch_fifo, 29 | task_uart_fill_fifo, 30 | task_uart_bridge, 31 | task_alert_association, 32 | task_alert_disassociation, 33 | task_reset, 34 | task_run_sequencer, 35 | task_periodic_i2c_sensors, 36 | task_init_displays, 37 | task_received_command, 38 | task_display_update, 39 | task_wlan_recovery, 40 | task_remote_trigger, 41 | task_wlan_reconnect, 42 | task_pins_changed_gpio, 43 | task_pins_changed_mcp, 44 | task_pins_changed_pcf, 45 | task_display_load_picture_worker, 46 | task_invalid, 47 | task_size = task_invalid, 48 | } task_id_t; 49 | 50 | enum 51 | { 52 | task_received_command_text, 53 | task_received_command_packet, 54 | task_received_command_uart 55 | }; 56 | 57 | typedef struct 58 | { 59 | string_t *src; 60 | string_t *src_oob; 61 | string_t *dst; 62 | int dst_data_pad_offset; 63 | int dst_data_oob_offset; 64 | } app_params_t; 65 | 66 | typedef struct attr_packed 67 | { 68 | int16_t io; 69 | int16_t pin; 70 | } trigger_t; 71 | 72 | assert_size(trigger_t, 4); 73 | 74 | extern trigger_t trigger_alert; 75 | extern trigger_t pcint_alert; 76 | 77 | extern bool uart_bridge_active; 78 | 79 | void dispatch_init1(void); 80 | void dispatch_init2(void); 81 | bool dispatch_post_task(task_prio_t, task_id_t, uint32_t parameter_32, uint16_t parameter_16, uint8_t parameter_8); 82 | #endif 83 | -------------------------------------------------------------------------------- /uart.h: -------------------------------------------------------------------------------- 1 | #ifndef uart_h 2 | #define uart_h 3 | 4 | #include "util.h" 5 | #include "queue.h" 6 | #include "sdk.h" 7 | 8 | #include 9 | #include 10 | 11 | typedef enum attr_packed 12 | { 13 | parity_none, 14 | parity_even, 15 | parity_odd, 16 | parity_error 17 | } uart_parity_t; 18 | 19 | typedef enum 20 | { 21 | uart_dir_none, 22 | uart_dir_tx, 23 | uart_dir_rx, 24 | } uart_direction_t; 25 | 26 | assert_size(uart_parity_t, 1); 27 | 28 | typedef struct attr_packed 29 | { 30 | uint8_t data_bits; 31 | uart_parity_t parity; 32 | uint8_t stop_bits; 33 | uint32_t baud_rate; 34 | } uart_parameters_t; 35 | 36 | assert_size(uart_parameters_t, 7); 37 | 38 | void uart_task(struct ETSEventTag *event); 39 | void uart_parity_to_string(string_t *dst, uart_parity_t); 40 | char uart_parity_to_char(uart_parity_t); 41 | uart_parity_t uart_string_to_parity(const string_t *src); 42 | void uart_parameters_to_string(string_t *dst, const uart_parameters_t *); 43 | void uart_init(void); 44 | void uart_baudrate(unsigned int uart, unsigned int baudrate); 45 | void uart_data_bits(unsigned int uart, unsigned int data_bits); 46 | void uart_stop_bits(unsigned int uart, unsigned int stop_bits); 47 | void uart_parity(unsigned int uart, uart_parity_t parity); 48 | void uart_loopback(unsigned int, bool); 49 | bool uart_invert(unsigned int, uart_direction_t, bool enable); 50 | void uart_autofill(unsigned int uart, bool enable, unsigned int character); 51 | void uart_is_autofill(unsigned int uart, bool *enable, unsigned int *character); 52 | bool uart_full(unsigned int uart); 53 | void uart_send(unsigned int, unsigned int); 54 | void uart_send_string(unsigned int, const string_t *); 55 | void uart_flush(unsigned int); 56 | bool uart_empty(void); 57 | unsigned int uart_receive(void); 58 | void uart_clear_receive_queue(unsigned int); 59 | void uart_set_initial(unsigned int uart); 60 | void uart_task_handler_fetch_fifo(unsigned int uart); 61 | void uart_task_handler_fill_fifo(unsigned int uart); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/ping.h: -------------------------------------------------------------------------------- 1 | #ifndef __PING_H__ 2 | #define __PING_H__ 3 | #include "lwip/ip_addr.h" 4 | #include "lwip/icmp.h" 5 | /** 6 | * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used 7 | */ 8 | #ifndef PING_USE_SOCKETS 9 | #define PING_USE_SOCKETS LWIP_SOCKET 10 | #endif 11 | 12 | /** 13 | * PING_DEBUG: Enable debugging for PING. 14 | */ 15 | #ifndef PING_DEBUG 16 | #define PING_DEBUG LWIP_DBG_OFF 17 | #endif 18 | 19 | /** ping receive timeout - in milliseconds */ 20 | #ifndef PING_RCV_TIMEO 21 | #define PING_RCV_TIMEO 1000 22 | #endif 23 | 24 | /** ping delay - in milliseconds */ 25 | #ifndef PING_COARSE 26 | #define PING_COARSE 1000 27 | #endif 28 | 29 | /** ping identifier - must fit on a u16_t */ 30 | #ifndef PING_ID 31 | #define PING_ID 0xAFAF 32 | #endif 33 | 34 | /** ping additional data size to include in the packet */ 35 | #ifndef PING_DATA_SIZE 36 | #define PING_DATA_SIZE 32 37 | #endif 38 | 39 | /** ping result action - no default action */ 40 | #ifndef PING_RESULT 41 | #define PING_RESULT(ping_ok) 42 | #endif 43 | 44 | #define DEFAULT_PING_MAX_COUNT 4 45 | #define PING_TIMEOUT_MS 1000 46 | 47 | typedef void (* ping_recv_function)(void* arg, void *pdata); 48 | typedef void (* ping_sent_function)(void* arg, void *pdata); 49 | 50 | struct ping_option{ 51 | uint32 count; 52 | uint32 ip; 53 | uint32 coarse_time; 54 | ping_recv_function recv_function; 55 | ping_sent_function sent_function; 56 | void* reverse; 57 | }; 58 | 59 | struct ping_msg{ 60 | struct ping_option *ping_opt; 61 | struct raw_pcb *ping_pcb; 62 | uint32 ping_start; 63 | uint32 ping_sent; 64 | uint32 timeout_count; 65 | uint32 max_count; 66 | uint32 sent_count; 67 | uint32 coarse_time; 68 | }; 69 | 70 | struct ping_resp{ 71 | uint32 total_count; 72 | uint32 resp_time; 73 | uint32 seqno; 74 | uint32 timeout_count; 75 | uint32 bytes; 76 | uint32 total_bytes; 77 | uint32 total_time; 78 | sint8 ping_err; 79 | }; 80 | 81 | bool ping_start(struct ping_option *ping_opt); 82 | bool ping_regist_recv(struct ping_option *ping_opt, ping_recv_function ping_recv); 83 | bool ping_regist_sent(struct ping_option *ping_opt, ping_sent_function ping_sent); 84 | 85 | #endif /* __PING_H__ */ 86 | -------------------------------------------------------------------------------- /display.h: -------------------------------------------------------------------------------- 1 | #ifndef display_h 2 | #define display_h 3 | 4 | #include "util.h" 5 | #include "application.h" 6 | #include "spi.h" 7 | 8 | #include 9 | #include 10 | 11 | void display_init(void); 12 | void display_periodic(void); 13 | bool display_detected(void); 14 | 15 | enum 16 | { 17 | display_buffer_size = 64, 18 | }; 19 | 20 | typedef enum 21 | { 22 | display_pixel_mode_none = 0, 23 | display_pixel_mode_1 = 1, 24 | display_pixel_mode_16_rgb = 16, 25 | display_pixel_mode_24_rgb = 24, 26 | } display_pixel_mode_t; 27 | 28 | typedef struct 29 | { 30 | char name[32]; 31 | unsigned int columns; 32 | unsigned int rows; 33 | unsigned int cell_width; 34 | unsigned int cell_height; 35 | unsigned int width; 36 | unsigned int height; 37 | display_pixel_mode_t pixel_mode; 38 | } display_info_t; 39 | 40 | typedef const struct 41 | { 42 | bool (* const init_fn)(void); 43 | bool (* const info_fn)(display_info_t *); 44 | bool (* const begin_fn)(unsigned int slot, bool logmode); 45 | bool (* const output_fn)(unsigned int amount, const unsigned int unicode[]); 46 | bool (* const end_fn)(void); 47 | bool (* const bright_fn)(int brightness); 48 | bool (* const show_time_start_fn)(unsigned int, unsigned int); 49 | bool (* const show_time_stop_fn)(void); 50 | bool (* const plot_fn)(unsigned int pixel_amount, int x, int y, string_t *pixels); 51 | bool (* const freeze_fn)(bool active); 52 | } display_hooks_t; 53 | 54 | assert_size(display_hooks_t, 40); 55 | 56 | extern uint8_t display_buffer[display_buffer_size]; 57 | bool display_get_info(display_info_t *); 58 | bool display_load_picture_slot(unsigned int slot); 59 | void display_picture_load_worker(void); 60 | 61 | app_action_t application_function_display_brightness(app_params_t *); 62 | app_action_t application_function_display_dump(app_params_t *); 63 | app_action_t application_function_display_default_message(app_params_t *); 64 | app_action_t application_function_display_flip_timeout(app_params_t *); 65 | app_action_t application_function_display_set(app_params_t *); 66 | app_action_t application_function_display_picture_load(app_params_t *); 67 | app_action_t application_function_display_plot(app_params_t *); 68 | app_action_t application_function_display_freeze(app_params_t *); 69 | #endif 70 | -------------------------------------------------------------------------------- /rboot-interface.h: -------------------------------------------------------------------------------- 1 | #ifndef rboot_interface_h 2 | #define rboot_interface_h 3 | 4 | #include "attribute.h" 5 | #include "util.h" 6 | 7 | #include 8 | #include 9 | 10 | // Make sure these entries exactly mirror the ones in rboot/*.h 11 | 12 | enum 13 | { 14 | rboot_if_conf_magic = 0xe1, 15 | rboot_if_conf_version = 0x01, 16 | rboot_if_conf_mode_standard = 0x00, 17 | rboot_if_conf_mode_unused_1 = 0x01, 18 | rboot_if_conf_mode_temp_rom = 0x02, 19 | rboot_if_conf_mode_unused_2 = 0x04, 20 | rboot_if_conf_mode_unused_3 = 0x08, 21 | rboot_if_rtc_address = 0x40, 22 | rboot_if_rtc_checksum_init = 0xef, 23 | rboot_if_rtc_magic = 0x2334ae68, 24 | }; 25 | 26 | typedef struct 27 | { 28 | uint8_t magic; // this should be rboot_if_conf_magic 29 | uint8_t version; // this should be rboot_if_conf_version 30 | uint8_t boot_mode; // this should be either rboot_if_conf_mode_standard or rboot_if_conf_mode_temp_rom 31 | uint8_t slot_current; // current active slot, will be used for next boot 32 | uint8_t unused_0; 33 | uint8_t slot_count; // amount of slots, currently always four for compatibility, although only two are used 34 | uint8_t unused_1; 35 | uint8_t unused_2; 36 | uint32_t slots[4]; // addresses in flash where slots are loaded 37 | uint8_t padding[40]; // padding 38 | } rboot_if_config_t; 39 | 40 | assert_size(rboot_if_config_t, 64); 41 | 42 | typedef struct 43 | { 44 | uint32_t magic; // this should be rboot_if_rtc_magic 45 | uint8_t next_mode; // use rboot_if_conf_mode_standard or rboot_if_conf_mode_temp_rom 46 | uint8_t last_mode; // reflects last boot mode 47 | uint8_t last_slot; // reflects last boot slot 48 | uint8_t temporary_slot; // the next slot to boot when next_mode == rboot_if_conf_mode_temp_rom 49 | uint8_t checksum; 50 | } rboot_if_rtc_config_t; 51 | 52 | assert_size(rboot_if_rtc_config_t, 12); 53 | 54 | const char * rboot_if_boot_mode(unsigned int index); 55 | bool rboot_if_read_config(rboot_if_config_t *config); 56 | bool rboot_if_write_config(const rboot_if_config_t *config); 57 | bool rboot_if_read_rtc_ram(rboot_if_rtc_config_t *config); 58 | bool rboot_if_write_rtc_ram(rboot_if_rtc_config_t *config); 59 | void rboot_if_info(string_t *dst); 60 | unsigned int rboot_if_mapped_slot(void); 61 | #endif 62 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * time.h 3 | * 4 | * Created on: May 31, 2016 5 | * Author: liuhan 6 | */ 7 | 8 | #ifndef TIME_H_ 9 | #define TIME_H_ 10 | #include "lwip/sntp.h" 11 | #include 12 | 13 | #define PERIPHS_RTC_BASEADDR 0x60000700 14 | #define REG_RTC_BASE PERIPHS_RTC_BASEADDR 15 | #define RTC_STORE3 (REG_RTC_BASE + 0x03C) 16 | 17 | #define ETS_UNCACHED_ADDR(addr) (addr) 18 | #define READ_PERI_REG(addr) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) 19 | #define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val) 20 | 21 | /***************************RTC TIME OPTION***************************************/ 22 | // daylight settings 23 | // Base calculated with value obtained from NTP server (64 bits) 24 | #define sntp_base (*((uint64_t*)RTC_STORE0)) 25 | // Timer value when base was obtained 26 | #define TIM_REF_SET(value) WRITE_PERI_REG(RTC_STORE2, value) 27 | #define TIM_REF_GET() READ_PERI_REG(RTC_STORE2) 28 | 29 | // Setters and getters for CAL, TZ and DST. 30 | #define RTC_CAL_SET(val) do {uint32_t value = READ_PERI_REG(RTC_STORE3);\ 31 | value |= ((val) & 0x0000FFFF);\ 32 | WRITE_PERI_REG(RTC_STORE3, value);\ 33 | }while(0) 34 | #define RTC_DST_SET(val) do {uint32_t value = READ_PERI_REG(RTC_STORE3);\ 35 | value |= (((val)<<16) & 0x00010000);\ 36 | WRITE_PERI_REG(RTC_STORE3, value);\ 37 | }while(0) 38 | #define RTC_TZ_SET(val) do {uint32_t value = READ_PERI_REG(RTC_STORE3);\ 39 | value |= (((val)<<24) & 0xFF000000);\ 40 | WRITE_PERI_REG(RTC_STORE3, value);\ 41 | }while(0) 42 | 43 | #define RTC_CAL_GET() (READ_PERI_REG(RTC_STORE3) & 0x0000FFFF) 44 | #define RTC_DST_GET() ((READ_PERI_REG(RTC_STORE3) & 0x00010000)>>16) 45 | #define RTC_TZ_GET() ((((int)READ_PERI_REG(RTC_STORE3)) & ((int)0xFF000000))>>24) 46 | void system_update_rtc(time_t t, uint32_t us); 47 | time_t sntp_get_rtc_time(int32_t *us); 48 | 49 | /*int gettimeofday(struct timeval* t, void* timezone);*/ 50 | void updateTime(uint32_t ms); 51 | bool configTime(int timezone, int daylightOffset, char *server1, char *server2, char *server3, bool enable); 52 | time_t time(time_t *t); 53 | unsigned long millis(void); 54 | unsigned long micros(void); 55 | #endif /* TIME_H_ */ 56 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/espconn_tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef __ESPCONN_TCP_H__ 2 | #define __ESPCONN_TCP_H__ 3 | 4 | #ifndef ESPCONN_TCP_DEBUG 5 | #define ESPCONN_TCP_DEBUG LWIP_DBG_OFF 6 | #endif 7 | #include "lwip/app/espconn.h" 8 | 9 | #ifndef ESPCONN_TCP_TIMER 10 | #define ESPCONN_TCP_TIMER 40 11 | #endif 12 | 13 | #define espconn_keepalive_enable(pcb) ((pcb)->so_options |= SOF_KEEPALIVE) 14 | #define espconn_keepalive_disable(pcb) ((pcb)->so_options &= ~SOF_KEEPALIVE) 15 | 16 | #define espconn_manual_recv_disabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_MANUALRECV) != 0) 17 | #define espconn_manual_recv_enabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_MANUALRECV) == 0) 18 | 19 | /****************************************************************************** 20 | * FunctionName : espconn_kill_oldest_pcb 21 | * Description : A oldest incoming connection has been killed. 22 | * Parameters : none 23 | * Returns : none 24 | *******************************************************************************/ 25 | 26 | extern void espconn_kill_oldest_pcb(void); 27 | 28 | /****************************************************************************** 29 | * FunctionName : espconn_tcp_disconnect 30 | * Description : A new incoming connection has been disconnected. 31 | * Parameters : espconn -- the espconn used to disconnect with host 32 | * Returns : none 33 | *******************************************************************************/ 34 | 35 | extern void espconn_tcp_disconnect(espconn_msg *pdiscon,u8 type); 36 | 37 | /****************************************************************************** 38 | * FunctionName : espconn_tcp_client 39 | * Description : Initialize the client: set up a connect PCB and bind it to 40 | * the defined port 41 | * Parameters : espconn -- the espconn used to build client 42 | * Returns : none 43 | *******************************************************************************/ 44 | 45 | extern sint8 espconn_tcp_client(struct espconn* espconn); 46 | 47 | /****************************************************************************** 48 | * FunctionName : espconn_tcp_server 49 | * Description : Initialize the server: set up a listening PCB and bind it to 50 | * the defined port 51 | * Parameters : espconn -- the espconn used to build server 52 | * Returns : none 53 | *******************************************************************************/ 54 | 55 | extern sint8 espconn_tcp_server(struct espconn *espconn); 56 | 57 | #endif /* __CLIENT_TCP_H__ */ 58 | 59 | -------------------------------------------------------------------------------- /spi.h: -------------------------------------------------------------------------------- 1 | #ifndef _spi_h_ 2 | #define _spi_h_ 3 | 4 | #include "io_gpio.h" 5 | #include "stats.h" 6 | #include "eagle.h" 7 | 8 | #include 9 | #include 10 | 11 | typedef enum 12 | { 13 | spi_mode_none = 0, // CPOL CPHA 14 | spi_mode_0, // 0 0 15 | spi_mode_1, // 0 1 16 | spi_mode_2, // 1 0 17 | spi_mode_3, // 1 1 18 | spi_mode_size, 19 | } spi_mode_t; 20 | 21 | typedef enum 22 | { 23 | spi_clock_none = 0, 24 | spi_clock_80M, 25 | spi_clock_40M, 26 | spi_clock_27M, 27 | spi_clock_20M, 28 | spi_clock_16M, 29 | spi_clock_13M, 30 | spi_clock_11M, 31 | spi_clock_10M, 32 | spi_clock_9M, 33 | spi_clock_8M, 34 | spi_clock_7M, 35 | spi_clock_6M, 36 | spi_clock_5M, 37 | spi_clock_4M, 38 | spi_clock_3M, 39 | spi_clock_2M, 40 | spi_clock_1M, 41 | spi_clock_500k, 42 | spi_clock_250k, 43 | spi_clock_100k, 44 | spi_clock_50k, 45 | spi_clock_10k, 46 | spi_clock_1k, 47 | spi_clock_size, 48 | } spi_clock_t; 49 | 50 | extern const char help_description_spi_configure[]; 51 | extern const char help_description_spi_start[]; 52 | extern const char help_description_spi_write[]; 53 | extern const char help_description_spi_transmit[]; 54 | extern const char help_description_spi_receive[]; 55 | extern const char help_description_spi_finish[]; 56 | 57 | attr_result_used bool spi_init(string_t *error, unsigned int io); 58 | attr_result_used bool spi_configure(string_t *error, spi_mode_t mode, bool cs_hold, int user_cs_io, int user_cs_pin); 59 | attr_result_used bool spi_start(string_t *error); 60 | attr_result_used unsigned int spi_write_bits_used(void); 61 | attr_result_used unsigned int spi_write_bits_available(void); 62 | attr_result_used bool spi_write(unsigned int bits, uint32_t value); 63 | attr_result_used bool spi_transmit(string_t *error, spi_clock_t clock, 64 | unsigned int command_length_bits, unsigned int command, unsigned int address_length_bits, unsigned int address, unsigned int skip_bits, unsigned int receive_bytes); 65 | attr_result_used bool spi_receive(string_t *error, unsigned int receive_bytes, uint8_t *receive_data); 66 | attr_result_used bool spi_finish(string_t *error); 67 | 68 | attr_result_used app_action_t application_function_spi_configure(app_params_t *); 69 | attr_result_used app_action_t application_function_spi_start(app_params_t *); 70 | attr_result_used app_action_t application_function_spi_write(app_params_t *); 71 | attr_result_used app_action_t application_function_spi_transmit(app_params_t *); 72 | attr_result_used app_action_t application_function_spi_receive(app_params_t *); 73 | attr_result_used app_action_t application_function_spi_finish(app_params_t *); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /ota.h: -------------------------------------------------------------------------------- 1 | #ifndef __ota_h__ 2 | #define __ota_h__ 3 | 4 | #if !defined(__espif__) && !defined(__esp32__) 5 | #include "util.h" 6 | #include "dispatch.h" 7 | #include "attribute.h" 8 | #endif 9 | 10 | #include 11 | 12 | enum 13 | { 14 | packet_header_soh = 0x01, 15 | packet_header_version = 2, 16 | packet_header_id = 0x4afb, 17 | }; 18 | 19 | typedef struct attr_packed 20 | { 21 | uint8_t soh; // 0 22 | uint8_t version; // 1 23 | uint16_t id; // 2 24 | uint16_t length; // 4 25 | uint16_t data_offset; // 6 26 | uint16_t data_pad_offset; // 8 27 | uint16_t oob_data_offset; // 10 28 | uint16_t broadcast_groups; // 12 29 | union 30 | { 31 | struct attr_packed 32 | { 33 | unsigned int md5_32_requested:1; 34 | unsigned int md5_32_provided:1; 35 | unsigned int transaction_id_provided:1; 36 | unsigned int spare_3:1; 37 | unsigned int spare_4:1; 38 | unsigned int spare_5:1; 39 | unsigned int spare_6:1; 40 | unsigned int spare_7:1; 41 | unsigned int spare_8:1; 42 | unsigned int spare_9:1; 43 | unsigned int spare_10:1; 44 | unsigned int spare_11:1; 45 | unsigned int spare_12:1; 46 | unsigned int spare_13:1; 47 | unsigned int spare_14:1; 48 | unsigned int spare_15:1; 49 | } flag; // 14 50 | uint16_t flags; // 14 51 | }; 52 | uint32_t transaction_id; // 16 53 | uint32_t spare_0; // 20 54 | uint32_t spare_1; // 24 55 | uint32_t checksum; // 28 56 | } packet_header_t; 57 | 58 | assert_field(packet_header_t, soh, 0); 59 | assert_field(packet_header_t, version, 1); 60 | assert_field(packet_header_t, id, 2); 61 | assert_field(packet_header_t, length, 4); 62 | assert_field(packet_header_t, data_offset, 6); 63 | assert_field(packet_header_t, data_pad_offset, 8); 64 | assert_field(packet_header_t, oob_data_offset, 10); 65 | assert_field(packet_header_t, broadcast_groups, 12); 66 | assert_field(packet_header_t, flag, 14); 67 | assert_field(packet_header_t, flags, 14); 68 | assert_field(packet_header_t, transaction_id, 16); 69 | assert_field(packet_header_t, spare_0, 20); 70 | assert_field(packet_header_t, spare_1, 24); 71 | assert_field(packet_header_t, checksum, 28); 72 | assert_size(packet_header_t, 32); 73 | 74 | #if !defined(__espif__) && !defined(__esp32__) 75 | app_action_t application_function_flash_info(app_params_t *); 76 | app_action_t application_function_flash_write(app_params_t *); 77 | app_action_t application_function_flash_read(app_params_t *); 78 | app_action_t application_function_flash_checksum(app_params_t *); 79 | app_action_t application_function_flash_bench(app_params_t *); 80 | app_action_t application_function_flash_select(app_params_t *); 81 | #endif 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/dhcpserver.h: -------------------------------------------------------------------------------- 1 | #ifndef __DHCPS_H__ 2 | #define __DHCPS_H__ 3 | 4 | #define USE_DNS 5 | 6 | typedef struct dhcps_state{ 7 | int16_t state; 8 | } dhcps_state; 9 | 10 | // dhcpclient DHCP msg 11 | typedef struct dhcps_msg { 12 | uint8_t op, htype, hlen, hops; 13 | uint8_t xid[4]; 14 | uint16_t secs, flags; 15 | uint8_t ciaddr[4]; 16 | uint8_t yiaddr[4]; 17 | uint8_t siaddr[4]; 18 | uint8_t giaddr[4]; 19 | uint8_t chaddr[16]; 20 | uint8_t sname[64]; 21 | uint8_t file[128]; 22 | uint8_t options[312]; 23 | }dhcps_msg; 24 | 25 | typedef enum { 26 | DHCPS_TYPE_DYNAMIC, 27 | DHCPS_TYPE_STATIC 28 | } dhcps_type_t; 29 | 30 | typedef enum { 31 | DHCPS_STATE_ONLINE, 32 | DHCPS_STATE_OFFLINE 33 | } dhcps_state_t; 34 | 35 | struct dhcps_pool{ 36 | struct ip_addr ip; 37 | uint8_t mac[6]; 38 | uint32_t lease_timer; 39 | dhcps_type_t type; 40 | dhcps_state_t state; 41 | 42 | }; 43 | 44 | typedef struct _list_node{ 45 | void *pnode; 46 | struct _list_node *pnext; 47 | }list_node; 48 | 49 | extern uint32_t dhcps_lease_time; 50 | #define DHCPS_LEASE_TIMER dhcps_lease_time //0x05A0 51 | #define DHCPS_MAX_LEASE 0x64 52 | #define BOOTP_BROADCAST 0x8000 53 | 54 | #define DHCP_REQUEST 1 55 | #define DHCP_REPLY 2 56 | #define DHCP_HTYPE_ETHERNET 1 57 | #define DHCP_HLEN_ETHERNET 6 58 | #define DHCP_MSG_LEN 236 59 | 60 | #define DHCPS_SERVER_PORT 67 61 | #define DHCPS_CLIENT_PORT 68 62 | 63 | #define DHCPDISCOVER 1 64 | #define DHCPOFFER 2 65 | #define DHCPREQUEST 3 66 | #define DHCPDECLINE 4 67 | #define DHCPACK 5 68 | #define DHCPNAK 6 69 | #define DHCPRELEASE 7 70 | 71 | #define DHCP_OPTION_SUBNET_MASK 1 72 | #define DHCP_OPTION_ROUTER 3 73 | #define DHCP_OPTION_DNS_SERVER 6 74 | #define DHCP_OPTION_REQ_IPADDR 50 75 | #define DHCP_OPTION_LEASE_TIME 51 76 | #define DHCP_OPTION_MSG_TYPE 53 77 | #define DHCP_OPTION_SERVER_ID 54 78 | #define DHCP_OPTION_INTERFACE_MTU 26 79 | #define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 80 | #define DHCP_OPTION_BROADCAST_ADDRESS 28 81 | #define DHCP_OPTION_REQ_LIST 55 82 | #define DHCP_OPTION_END 255 83 | 84 | //#define USE_CLASS_B_NET 1 85 | #define DHCPS_DEBUG 0 86 | #define MAX_STATION_NUM 8 87 | 88 | #define DHCPS_STATE_OFFER 1 89 | #define DHCPS_STATE_DECLINE 2 90 | #define DHCPS_STATE_ACK 3 91 | #define DHCPS_STATE_NAK 4 92 | #define DHCPS_STATE_IDLE 5 93 | #define DHCPS_STATE_RELEASE 6 94 | 95 | #define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0) 96 | 97 | void dhcps_start(struct ip_info *info); 98 | void dhcps_stop(void); 99 | 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/espconn_udp.h: -------------------------------------------------------------------------------- 1 | #ifndef __ESPCONN_UDP_H__ 2 | #define __ESPCONN_UDP_H__ 3 | 4 | #ifndef ESPCONN_UDP_DEBUG 5 | #define ESPCONN_UDP_DEBUG LWIP_DBG_OFF 6 | #endif 7 | 8 | #include "lwip/app/espconn.h" 9 | 10 | /****************************************************************************** 11 | * FunctionName : espconn_udp_client 12 | * Description : Initialize the client: set up a PCB and bind it to the port 13 | * Parameters : pespconn -- the espconn used to build client 14 | * Returns : none 15 | *******************************************************************************/ 16 | 17 | extern sint8 espconn_udp_client(struct espconn *pespconn); 18 | 19 | /****************************************************************************** 20 | * FunctionName : espconn_udp_disconnect 21 | * Description : A new incoming connection has been disconnected. 22 | * Parameters : espconn -- the espconn used to disconnect with host 23 | * Returns : none 24 | *******************************************************************************/ 25 | 26 | extern void espconn_udp_disconnect(espconn_msg *pdiscon); 27 | 28 | /****************************************************************************** 29 | * FunctionName : espconn_udp_server 30 | * Description : Initialize the server: set up a PCB and bind it to the port 31 | * Parameters : pespconn -- the espconn used to build server 32 | * Returns : none 33 | *******************************************************************************/ 34 | 35 | extern sint8 espconn_udp_server(struct espconn *espconn); 36 | 37 | /****************************************************************************** 38 | * FunctionName : espconn_udp_sent 39 | * Description : sent data for client or server 40 | * Parameters : void *arg -- client or server to send 41 | * uint8* psent -- Data to send 42 | * uint16 length -- Length of data to send 43 | * Returns : none 44 | *******************************************************************************/ 45 | 46 | extern err_t espconn_udp_sent(void *arg, uint8 *psent, uint16 length); 47 | 48 | /****************************************************************************** 49 | * FunctionName : espconn_udp_sendto 50 | * Description : sent data for UDP 51 | * Parameters : void *arg -- UDP to send 52 | * uint8* psent -- Data to send 53 | * uint16 length -- Length of data to send 54 | * Returns : return espconn error code. 55 | * - ESPCONN_OK. Successful. No error occured. 56 | * - ESPCONN_MEM. Out of memory. 57 | * - ESPCONN_RTE. Could not find route to destination address. 58 | * - More errors could be returned by lower protocol layers. 59 | *******************************************************************************/ 60 | extern err_t espconn_udp_sendto(void *arg, uint8 *psent, uint16 length); 61 | 62 | #endif /* __ESPCONN_UDP_H__ */ 63 | 64 | 65 | -------------------------------------------------------------------------------- /io_gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef io_gpio_h 2 | #define io_gpio_h 3 | 4 | #include "io.h" 5 | #include "util.h" 6 | #include "eagle.h" 7 | 8 | #include 9 | #include 10 | 11 | typedef enum 12 | { 13 | gpio_i2s_pin_none, 14 | gpio_i2s_pin_input_bitclock, 15 | gpio_i2s_pin_input_wordclock, 16 | gpio_i2s_pin_input_data, 17 | gpio_i2s_pin_output_bitclock, 18 | gpio_i2s_pin_output_wordclock, 19 | gpio_i2s_pin_output_data, 20 | } gpio_i2s_pin_t; 21 | 22 | extern const io_info_entry_t io_info_entry_gpio; 23 | 24 | void io_gpio_pins_changed(uint32_t pin_interrupt_status, uint16_t pin_value); 25 | int io_gpio_get_uart_from_pin(unsigned int pin); 26 | gpio_i2s_pin_t io_gpio_get_i2s_from_pin(unsigned int pin); 27 | bool io_gpio_pin_usable(unsigned int pin); 28 | bool io_gpio_pwm1_width_set(unsigned int period, bool load, bool save); 29 | unsigned int io_gpio_pwm1_width_get(void); 30 | 31 | // generic 32 | 33 | attr_inline uint32_t gpio_pin_addr(int pin) 34 | { 35 | return(GPIO_PIN0_ADDRESS + (pin << 2)); 36 | } 37 | 38 | // read / write registers 39 | 40 | attr_inline uint32_t read_peri_reg(uint32_t addr) 41 | { 42 | volatile uint32_t *ptr = (volatile uint32_t *)addr; 43 | 44 | return(*ptr); 45 | } 46 | 47 | attr_inline void write_peri_reg(volatile uint32_t addr, uint32_t value) 48 | { 49 | volatile uint32_t *ptr = (volatile uint32_t *)addr; 50 | 51 | *ptr = value; 52 | } 53 | 54 | attr_inline void clear_peri_reg_mask(volatile uint32_t addr, uint32_t mask) 55 | { 56 | write_peri_reg(addr, read_peri_reg(addr) & ~mask); 57 | } 58 | 59 | attr_inline void set_peri_reg_mask(volatile uint32_t addr, uint32_t mask) 60 | { 61 | write_peri_reg(addr, read_peri_reg(addr) | mask); 62 | } 63 | 64 | attr_inline void clear_set_peri_reg_mask(uint32_t addr, uint32_t clearmask, uint32_t setmask) 65 | { 66 | uint32_t regval; 67 | 68 | regval = read_peri_reg(addr); 69 | regval &= ~clearmask; 70 | regval |= setmask; 71 | write_peri_reg(addr, regval); 72 | } 73 | 74 | // read write GPIO registers 75 | 76 | attr_inline uint32_t gpio_reg_read(int reg) 77 | { 78 | return(read_peri_reg(PERIPHS_GPIO_BASEADDR + reg)); 79 | } 80 | 81 | attr_inline void gpio_reg_write(int reg, uint32_t value) 82 | { 83 | write_peri_reg(PERIPHS_GPIO_BASEADDR + reg, value); 84 | } 85 | 86 | // read input 87 | 88 | attr_inline uint32_t gpio_get_all(void) 89 | { 90 | return(gpio_reg_read(GPIO_IN_ADDRESS) & 0x0000ffff); 91 | } 92 | 93 | attr_inline unsigned int gpio_get(int io) 94 | { 95 | return(!!(gpio_reg_read(GPIO_IN_ADDRESS) & (1 << io))); 96 | } 97 | 98 | // set output low / high 99 | 100 | attr_inline void gpio_clear_mask(uint32_t mask) 101 | { 102 | gpio_reg_write(GPIO_OUT_W1TC_ADDRESS, mask); 103 | } 104 | 105 | attr_inline void gpio_set_mask(uint32_t mask) 106 | { 107 | gpio_reg_write(GPIO_OUT_W1TS_ADDRESS, mask); 108 | } 109 | 110 | attr_inline void gpio_set(int io, int onoff) 111 | { 112 | if(onoff) 113 | gpio_set_mask(1 << io); 114 | else 115 | gpio_clear_mask(1 << io); 116 | } 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /lwip-interface.h: -------------------------------------------------------------------------------- 1 | #ifndef lwip_interface_h 2 | #define lwip_interface_h 3 | 4 | #include "util.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | typedef enum 12 | { 13 | lwip_if_proto_tcp = 1 << 0, 14 | lwip_if_proto_udp = 1 << 1, 15 | lwip_if_proto_all = lwip_if_proto_tcp | lwip_if_proto_udp, 16 | } lwip_if_proto_t; 17 | 18 | struct _lwip_if_socket_t; 19 | 20 | typedef struct 21 | { 22 | bool tcp; 23 | bool udp; 24 | bool multicast; 25 | bool broadcast; 26 | int length; 27 | int overflow; 28 | int original_length; 29 | int parts; 30 | string_t *buffer_string; 31 | int buffer_size; 32 | char *buffer; 33 | const char *name; 34 | } lwip_if_callback_context_t; 35 | 36 | typedef void (*callback_data_received_fn_t)(struct _lwip_if_socket_t *, const lwip_if_callback_context_t *context); 37 | 38 | typedef struct _lwip_if_socket_t 39 | { 40 | struct 41 | { 42 | void *pcb; 43 | void *pbuf_send; 44 | } udp; 45 | 46 | struct 47 | { 48 | void *listen_pcb; 49 | void *pcb; 50 | } tcp; 51 | 52 | struct 53 | { 54 | unsigned int reboot_pending:1; 55 | 56 | struct 57 | { 58 | unsigned int tcp:1; 59 | unsigned int udp:1; 60 | } receive_buffer_locked; 61 | }; 62 | 63 | struct 64 | { 65 | unsigned int port; 66 | } local; 67 | 68 | struct 69 | { 70 | ip_addr_t address; 71 | unsigned int port; 72 | } peer; 73 | 74 | string_t *receive_buffer; 75 | string_t *send_buffer; 76 | int sending_remaining; 77 | int sent_unacked; 78 | 79 | char name[8]; 80 | 81 | callback_data_received_fn_t callback_data_received; 82 | 83 | } lwip_if_socket_t; 84 | 85 | assert_size(lwip_if_socket_t, 64); 86 | 87 | attr_nonnull bool lwip_if_received_tcp(lwip_if_socket_t *); 88 | attr_nonnull bool lwip_if_received_udp(lwip_if_socket_t *); 89 | attr_nonnull void lwip_if_receive_buffer_lock(lwip_if_socket_t *, lwip_if_proto_t); 90 | attr_nonnull void lwip_if_receive_buffer_unlock(lwip_if_socket_t *, lwip_if_proto_t); 91 | attr_nonnull bool lwip_if_send_buffer_locked(lwip_if_socket_t *); 92 | attr_nonnull unsigned int lwip_if_send_buffer_unacked(lwip_if_socket_t *); 93 | attr_nonnull bool lwip_if_send(lwip_if_socket_t *socket); 94 | attr_nonnull bool lwip_if_sendto(lwip_if_socket_t *socket, const ip_addr_t *address, unsigned int port); 95 | attr_nonnull bool lwip_if_close(lwip_if_socket_t *socket); 96 | attr_nonnull bool lwip_if_reboot(lwip_if_socket_t *socket); 97 | attr_nonnull bool lwip_if_socket_create(lwip_if_socket_t *socket, const char *name, string_t *receive_buffer, string_t *send_buffer, 98 | unsigned int port, bool create_tcp_socket, callback_data_received_fn_t callback_data_received); 99 | attr_nonnull bool lwip_if_join_mc(ip_addr_t); 100 | attr_nonnull void lwip_netstat_bound(string_t *); 101 | attr_nonnull void lwip_netstat_listening(string_t *); 102 | attr_nonnull void lwip_netstat_active(string_t *); 103 | attr_nonnull void lwip_netstat_timewait(string_t *); 104 | #endif 105 | -------------------------------------------------------------------------------- /resetserial.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char **argv) 9 | { 10 | int fd, flags; 11 | int delay = 10000; 12 | struct termios termios; 13 | unsigned int mode = 0; 14 | 15 | if((argc != 2) && (argc != 3)) 16 | { 17 | fprintf(stderr, "usage: resetserial [mode]\n"); 18 | fprintf(stderr, " mode = 0: default\n"); 19 | fprintf(stderr, " mode = 1: reset RTS+DTR\n"); 20 | fprintf(stderr, " mode = 2: reset DTR, set RTS\n"); 21 | fprintf(stderr, " mode = 3: reset RTS, set DTR\n"); 22 | fprintf(stderr, " mode = 4: set RTS+DTR\n"); 23 | exit(1); 24 | } 25 | 26 | if(argc == 3) 27 | mode = strtoul(argv[2], (char **)0, 0); 28 | 29 | if((fd = open(argv[1], O_RDONLY | O_NOCTTY, 0)) < 0) 30 | { 31 | perror("open"); 32 | exit(1); 33 | } 34 | 35 | if(tcgetattr(fd, &termios)) 36 | { 37 | perror("tcgetattr"); 38 | exit(1); 39 | } 40 | 41 | cfmakeraw(&termios); 42 | 43 | termios.c_cflag |= CLOCAL; 44 | termios.c_cflag &= ~HUPCL; 45 | 46 | if(tcsetattr(fd, TCSANOW, &termios)) 47 | { 48 | perror("tcsetattr"); 49 | exit(1); 50 | } 51 | 52 | if(ioctl(fd, TIOCMGET, &flags)) 53 | { 54 | perror("ioctl 1\n"); 55 | exit(1); 56 | } 57 | 58 | switch(mode) 59 | { 60 | case(0): 61 | { 62 | 63 | // set reset 64 | 65 | flags &= ~TIOCM_RTS; 66 | 67 | if(ioctl(fd, TIOCMSET, &flags)) 68 | { 69 | perror("ioctl 2\n"); 70 | exit(1); 71 | } 72 | 73 | usleep(delay); 74 | 75 | // set gpio0 76 | 77 | if(mode) 78 | flags |= TIOCM_DTR; 79 | else 80 | flags &= ~TIOCM_DTR; 81 | 82 | if(ioctl(fd, TIOCMSET, &flags)) 83 | { 84 | perror("ioctl 3\n"); 85 | exit(1); 86 | } 87 | 88 | usleep(delay); 89 | 90 | // release reset 91 | 92 | flags |= TIOCM_RTS; 93 | 94 | if(ioctl(fd, TIOCMSET, &flags)) 95 | { 96 | perror("ioctl 4\n"); 97 | exit(1); 98 | } 99 | 100 | usleep(delay); 101 | 102 | // release gpio0 103 | 104 | flags |= TIOCM_DTR; 105 | 106 | if(ioctl(fd, TIOCMSET, &flags)) 107 | { 108 | perror("ioctl 5\n"); 109 | exit(1); 110 | } 111 | 112 | break; 113 | } 114 | 115 | case(1): 116 | { 117 | flags &= ~TIOCM_RTS; 118 | flags &= ~TIOCM_DTR; 119 | 120 | if(ioctl(fd, TIOCMSET, &flags)) 121 | { 122 | perror("ioctl 12\n"); 123 | exit(1); 124 | } 125 | 126 | break; 127 | } 128 | 129 | case(2): 130 | { 131 | flags |= TIOCM_RTS; 132 | flags &= ~TIOCM_DTR; 133 | 134 | if(ioctl(fd, TIOCMSET, &flags)) 135 | { 136 | perror("ioctl 22\n"); 137 | exit(1); 138 | } 139 | 140 | break; 141 | } 142 | 143 | case(3): 144 | { 145 | flags &= ~TIOCM_RTS; 146 | flags |= TIOCM_DTR; 147 | 148 | if(ioctl(fd, TIOCMSET, &flags)) 149 | { 150 | perror("ioctl 32\n"); 151 | exit(1); 152 | } 153 | 154 | break; 155 | } 156 | 157 | case(4): 158 | { 159 | flags |= TIOCM_RTS; 160 | flags |= TIOCM_DTR; 161 | 162 | if(ioctl(fd, TIOCMSET, &flags)) 163 | { 164 | perror("ioctl 42\n"); 165 | exit(1); 166 | } 167 | 168 | break; 169 | } 170 | } 171 | 172 | exit(0); 173 | } 174 | -------------------------------------------------------------------------------- /i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef i2c_h 2 | #define i2c_h 3 | 4 | #include "util.h" 5 | 6 | #include 7 | 8 | enum 9 | { 10 | i2c_busses = 9 // 0 -> 1, 1 -> 2, ... and non-multiplexed bus = 0 11 | }; 12 | 13 | typedef enum 14 | { 15 | i2c_state_invalid = 0, 16 | i2c_state_idle, 17 | i2c_state_header_send, 18 | i2c_state_start_send, 19 | i2c_state_address_send, 20 | i2c_state_address_ack_receive, 21 | i2c_state_address_ack_received, 22 | i2c_state_data_send_data, 23 | i2c_state_data_send_ack_receive, 24 | i2c_state_data_send_ack_received, 25 | i2c_state_data_receive_data, 26 | i2c_state_data_receive_ack_send, 27 | i2c_state_stop_send, 28 | i2c_state_error, 29 | i2c_state_size = i2c_state_error 30 | } i2c_state_t; 31 | 32 | assert_size(i2c_state_t, 4); 33 | 34 | typedef enum 35 | { 36 | i2c_error_ok = 0, 37 | i2c_error_no_init, 38 | i2c_error_invalid_state_not_idle, 39 | i2c_error_invalid_state_idle, 40 | i2c_error_invalid_state_not_send_start, 41 | i2c_error_invalid_state_not_send_header, 42 | i2c_error_invalid_state_not_send_address_or_data, 43 | i2c_error_invalid_state_not_receive_ack, 44 | i2c_error_invalid_state_not_send_ack, 45 | i2c_error_bus_lock, 46 | i2c_error_sda_stuck, 47 | i2c_error_address_nak, 48 | i2c_error_data_nak, 49 | i2c_error_device_error_1, 50 | i2c_error_device_error_2, 51 | i2c_error_device_error_3, 52 | i2c_error_device_error_4, 53 | i2c_error_device_error_5, 54 | i2c_error_invalid_bus, 55 | i2c_error_out_of_range, 56 | i2c_error_disabled, 57 | i2c_error_secondary, 58 | i2c_error_in_use, 59 | i2c_error_in_use_on_bus_0, 60 | i2c_error_overflow, 61 | i2c_error_error, 62 | i2c_error_size = i2c_error_error 63 | } i2c_error_t; 64 | 65 | assert_size(i2c_error_t, 4); 66 | 67 | typedef struct attr_packed 68 | { 69 | unsigned int multiplexer:1; 70 | unsigned int buses:7; 71 | } i2c_info_t; 72 | 73 | assert_size(i2c_info_t, 1); 74 | 75 | void i2c_error_format_string(string_t *dst, i2c_error_t error); 76 | 77 | #define i2c_log(__prefix__,__error__) \ 78 | do { \ 79 | static roflash const char prefix_flash[] = __prefix__; \ 80 | string_new(, string_error, 128); \ 81 | string_append_cstr_flash(&string_error, prefix_flash); \ 82 | i2c_error_format_string(&string_error, __error__); \ 83 | string_append_cstr(&string_error, "\n"); \ 84 | log_from_flash_0(string_to_cstr(&string_error)); \ 85 | } while(0) 86 | 87 | void i2c_init(unsigned int sda_index, unsigned int scl_index); 88 | void i2c_speed_delay(unsigned int speed_delay); 89 | i2c_error_t i2c_select_bus(unsigned int bus); 90 | void i2c_get_info(i2c_info_t *); 91 | 92 | i2c_error_t i2c_send(int address, int length, const uint8_t *bytes); 93 | i2c_error_t i2c_receive(int address, int length, uint8_t *bytes); 94 | i2c_error_t i2c_send_receive(int address, int sendlength, const uint8_t *sendbytes, int receivelength, uint8_t *receivebytes); 95 | 96 | i2c_error_t i2c_send1(int address, int byte0); 97 | i2c_error_t i2c_send2(int address, int byte0, int byte1); 98 | i2c_error_t i2c_send3(int address, int byte0, int byte1, int byte2); 99 | i2c_error_t i2c_send4(int address, int byte0, int byte1, int byte2, int byte3); 100 | 101 | i2c_error_t i2c_send1_receive(int address, int byte0, int receivelength, uint8_t *receivebytes); 102 | 103 | i2c_error_t i2c_reset(void); 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef config_h 2 | #define config_h 3 | 4 | #include "uart.h" 5 | #include "util.h" 6 | #include "stats.h" 7 | 8 | #include 9 | #include 10 | 11 | enum 12 | { 13 | flag_none = 0 << 0, 14 | flag_strip_telnet = 1 << 0, 15 | flag_log_to_uart = 1 << 1, 16 | flag_log_date = 1 << 2, 17 | flag_log_time = 1 << 3, 18 | flag_cpu_high_speed = 1 << 4, 19 | flag_wlan_power_save = 1 << 5, 20 | flag_display_clock = 1 << 6, 21 | flag_mcp_int_push_pull = 1 << 7, 22 | flag_log_to_buffer = 1 << 8, 23 | flag_auto_sequencer = 1 << 9, 24 | flag_pwm1_extend = 1 << 10, 25 | flag_mcp_no_poll = 1 << 11, 26 | flag_cmd_from_uart = 1 << 17, 27 | flag_log_to_display = 1 << 18, 28 | flag_ssd_height_32 = 1 << 19, 29 | flag_pcf_no_poll = 1 << 20, 30 | }; 31 | 32 | void config_flags_to_string(bool nl, const char *, string_t *); 33 | bool config_flag_change(unsigned int flag, bool set); 34 | void config_flag_change_nosave(unsigned int flag, bool set); 35 | bool config_flag_change_from_string(const string_t *, bool set); 36 | 37 | bool config_init(void); 38 | bool config_dump(string_t *); 39 | bool config_open_write(void); 40 | bool config_close_write(void); 41 | void config_abort_write(void); 42 | 43 | unsigned int config_delete_flashptr(const char *match_name, bool wildcard, int index1, int index2); 44 | bool config_set_string_flashptr(const char *id, const char *value, int param1, int param2); 45 | bool config_set_int_flashptr(const char *match_name, int value, int index1, int index2); 46 | bool config_set_uint_flashptr(const char *match_name, unsigned int value, int index1, int index2); 47 | 48 | bool config_get_string_flashptr(const char *id, string_t *value, int param1, int param2); 49 | bool config_get_int_flashptr(const char *match_name, int *return_value, int param1, int param2); 50 | bool config_get_uint_flashptr(const char *match_name, unsigned int *return_value, int param1, int param2); 51 | 52 | #define config_get_string(name, value, p1, p2) \ 53 | ({ \ 54 | static roflash const char name_flash[] = name; \ 55 | config_get_string_flashptr(name_flash, value, p1, p2); \ 56 | }) 57 | 58 | #define config_get_int(name, value, p1, p2) \ 59 | ({ \ 60 | static roflash const char name_flash[] = name; \ 61 | config_get_int_flashptr(name_flash, value, p1, p2); \ 62 | }) 63 | 64 | #define config_get_uint(name, value, p1, p2) \ 65 | ({ \ 66 | static roflash const char name_flash[] = name; \ 67 | config_get_uint_flashptr(name_flash, value, p1, p2); \ 68 | }) 69 | 70 | #define config_delete(name, wildcard, p1, p2) \ 71 | ({ \ 72 | static roflash const char name_flash[] = name; \ 73 | config_delete_flashptr(name_flash, wildcard, p1, p2); \ 74 | }) 75 | 76 | #define config_set_string(name, value, p1, p2) \ 77 | ({ \ 78 | static roflash const char name_flash[] = name; \ 79 | config_set_string_flashptr(name_flash, value, p1, p2); \ 80 | }) 81 | 82 | #define config_set_int(name, value, p1, p2) \ 83 | ({ \ 84 | static roflash const char name_flash[] = name; \ 85 | config_set_int_flashptr(name_flash, value, p1, p2); \ 86 | }) 87 | 88 | #define config_set_uint(name, value, p1, p2) \ 89 | ({ \ 90 | static roflash const char name_flash[] = name; \ 91 | config_set_uint_flashptr(name_flash, value, p1, p2); \ 92 | }) 93 | 94 | attr_inline uint32_t config_flags_match(uint32_t match_flags) 95 | { 96 | extern unsigned int config_flags; 97 | return(!!(config_flags & match_flags)); 98 | } 99 | #endif 100 | -------------------------------------------------------------------------------- /init.c: -------------------------------------------------------------------------------- 1 | #include "init.h" 2 | 3 | #include "util.h" 4 | #include "io.h" 5 | #include "stats.h" 6 | #include "sys_time.h" 7 | #include "dispatch.h" 8 | #include "sequencer.h" 9 | #include "wlan.h" 10 | 11 | #include 12 | 13 | static void user_init2(void); 14 | void user_init(void); 15 | 16 | static const partition_item_t partition_items[] = 17 | { 18 | { SYSTEM_PARTITION_RF_CAL, RFCAL_OFFSET, RFCAL_SIZE, }, 19 | { SYSTEM_PARTITION_PHY_DATA, PHYDATA_OFFSET, PHYDATA_SIZE, }, 20 | { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_CONFIG_OFFSET, SYSTEM_CONFIG_SIZE, }, 21 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 0, USER_CONFIG_OFFSET, USER_CONFIG_SIZE, }, 22 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 1, OFFSET_BOOT, SIZE_BOOT, }, 23 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 2, OFFSET_RBOOT_CFG, SIZE_RBOOT_CFG, }, 24 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 3, OFFSET_IMG_0, SIZE_IMG, }, 25 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 4, OFFSET_IMG_1, SIZE_IMG, }, 26 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 5, SEQUENCER_FLASH_OFFSET_0, SEQUENCER_FLASH_SIZE, }, 27 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 6, SEQUENCER_FLASH_OFFSET_1, SEQUENCER_FLASH_SIZE, }, 28 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 7, PICTURE_FLASH_OFFSET_0, PICTURE_FLASH_SIZE, }, 29 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 8, PICTURE_FLASH_OFFSET_1, PICTURE_FLASH_SIZE, }, 30 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 9, FONT_FLASH_OFFSET_0, FONT_FLASH_SIZE, }, 31 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 10, FONT_FLASH_OFFSET_1, FONT_FLASH_SIZE, }, 32 | { SYSTEM_PARTITION_CUSTOMER_BEGIN + 11, MISC_FLASH_OFFSET, MISC_FLASH_SIZE, }, 33 | }; 34 | 35 | void user_spi_flash_dio_to_qio_pre_init(void); 36 | iram void user_spi_flash_dio_to_qio_pre_init(void) 37 | { 38 | } 39 | 40 | volatile uint32_t *stack_stack_sp_initial; 41 | int stack_stack_painted; 42 | static volatile uint32_t *stack_stack_paint_ptr; // this cannot be on the stack 43 | 44 | #pragma GCC diagnostic push 45 | #pragma GCC diagnostic ignored "-Wdangling-pointer" 46 | 47 | iram void stack_paint_stack(void) 48 | { 49 | // don't declare stack variables here, they will get overwritten 50 | 51 | volatile uint32_t sp; 52 | stack_stack_sp_initial = &sp; 53 | 54 | for(stack_stack_paint_ptr = (uint32_t *)stack_top; (stack_stack_paint_ptr < (uint32_t *)stack_bottom) && (stack_stack_paint_ptr < (volatile uint32_t *)stack_stack_sp_initial); stack_stack_paint_ptr++) 55 | { 56 | *stack_stack_paint_ptr = stack_paint_magic; 57 | stack_stack_painted += 4; 58 | } 59 | } 60 | 61 | #pragma GCC diagnostic pop 62 | 63 | void user_pre_init(void); 64 | iram void user_pre_init(void) 65 | { 66 | stat_flags.user_pre_init_called = 1; 67 | stat_flags.user_pre_init_success = system_partition_table_regist(partition_items, sizeof(partition_items) / sizeof(*partition_items), FLASH_SIZE_SDK); 68 | system_phy_set_powerup_option(3); /* request full calibration */ 69 | } 70 | 71 | uint32_t user_iram_memory_is_enabled(void); 72 | iram attr_const uint32_t user_iram_memory_is_enabled(void) 73 | { 74 | return(0); 75 | } 76 | 77 | void user_init(void) 78 | { 79 | stack_paint_stack(); 80 | 81 | system_set_os_print(0); 82 | dispatch_init1(); 83 | config_init(); 84 | uart_init(); 85 | uart_set_initial(0); 86 | uart_set_initial(1); 87 | os_install_putc1(&logchar_sdk); 88 | system_set_os_print(1); 89 | wlan_init(); 90 | system_init_done_cb(user_init2); 91 | } 92 | 93 | static void user_init2(void) 94 | { 95 | stat_heap_min = stat_heap_max = xPortGetFreeHeapSize(); 96 | 97 | dispatch_init2(); 98 | 99 | if(config_flags_match(flag_cpu_high_speed)) 100 | system_update_cpu_freq(160); 101 | else 102 | system_update_cpu_freq(80); 103 | 104 | application_init(); 105 | time_init(); 106 | io_init(); 107 | 108 | log("[system] boot done\n"); 109 | 110 | if(config_flags_match(flag_auto_sequencer)) 111 | sequencer_start(0, 1); 112 | } 113 | -------------------------------------------------------------------------------- /i2c_sensor.h: -------------------------------------------------------------------------------- 1 | #ifndef i2c_sensor_h 2 | #define i2c_sensor_h 3 | 4 | #include "config.h" 5 | #include "i2c.h" 6 | #include "util.h" 7 | 8 | #include 9 | #include 10 | 11 | typedef enum 12 | { 13 | i2c_sensor_opt3001 = 0, 14 | i2c_sensor_veml6075_uvindex, 15 | i2c_sensor_tmd2771, 16 | i2c_sensor_apds9930, 17 | i2c_sensor_apds9960, 18 | i2c_sensor_si114x_ultraviolet, 19 | i2c_sensor_si114x_visible_light, 20 | i2c_sensor_max44009, 21 | i2c_sensor_veml6070_38, 22 | i2c_sensor_veml6070_39, 23 | i2c_sensor_tsl2561_39, 24 | i2c_sensor_tsl2561_29, 25 | i2c_sensor_tsl2550, 26 | i2c_sensor_bh1750, 27 | i2c_sensor_tmp75_48, 28 | i2c_sensor_tmp75_49, 29 | i2c_sensor_tmp75_4a, 30 | i2c_sensor_tmp75_4f, 31 | i2c_sensor_ds7505_48, 32 | i2c_sensor_ds7505_49, 33 | i2c_sensor_ds7505_4a, 34 | i2c_sensor_ds7505_4f, 35 | i2c_sensor_ds1631_48, 36 | i2c_sensor_ds1631_49, 37 | i2c_sensor_ds1631_4a, 38 | i2c_sensor_ds1631_4f, 39 | i2c_sensor_ds1621_48, 40 | i2c_sensor_ds1621_49, 41 | i2c_sensor_ds1621_4a, 42 | i2c_sensor_ds1621_4f, 43 | i2c_sensor_tmp102_48, 44 | i2c_sensor_tmp102_49, 45 | i2c_sensor_lm75_48, 46 | i2c_sensor_lm75_49, 47 | i2c_sensor_lm75_4a, 48 | i2c_sensor_lm75_4f, 49 | i2c_sensor_mpl3115a2_temperature, 50 | i2c_sensor_mpl3115a2_airpressure, 51 | i2c_sensor_ccs811, 52 | i2c_sensor_sht30_temperature, 53 | i2c_sensor_sht30_humidity, 54 | i2c_sensor_mcp9808_temperature, 55 | i2c_sensor_hdc1080_temperature, 56 | i2c_sensor_hdc1080_humidity, 57 | i2c_sensor_htu21_temperature, 58 | i2c_sensor_htu21_humidity, 59 | i2c_sensor_bme680_temperature, 60 | i2c_sensor_bme680_airpressure, 61 | i2c_sensor_bme680_humidity, 62 | i2c_sensor_bme280_temperature, 63 | i2c_sensor_bme280_airpressure, 64 | i2c_sensor_bme280_humidity, 65 | i2c_sensor_bmp280_temperature, 66 | i2c_sensor_bmp280_airpressure, 67 | i2c_sensor_bmp085_temperature, 68 | i2c_sensor_bmp085_airpressure, 69 | i2c_sensor_am2320_temperature, 70 | i2c_sensor_am2320_humidity, 71 | i2c_sensor_hih6130_humidity, 72 | i2c_sensor_hih6130_temperature, 73 | i2c_sensor_digipicco_temperature, 74 | i2c_sensor_digipicco_humidity, 75 | i2c_sensor_tsl2591_29, 76 | i2c_sensor_tsl2591_28, 77 | i2c_sensor_aht10_temperature, 78 | i2c_sensor_aht10_humidity, 79 | i2c_sensor_veml6040, 80 | i2c_sensor_veml7700, 81 | i2c_sensor_error, 82 | i2c_sensor_none = i2c_sensor_error, 83 | i2c_sensor_size = i2c_sensor_error 84 | } i2c_sensor_t; 85 | 86 | assert_size(i2c_sensor_t, 4); 87 | 88 | typedef struct 89 | { 90 | unsigned int periodic_called; 91 | 92 | uint64_t detect_started_us; 93 | uint64_t detect_finished_us; 94 | unsigned int detect_started:1; 95 | unsigned int detect_finished:1; 96 | unsigned int detect_called; 97 | unsigned int detect_failed; 98 | unsigned int detect_succeeded; 99 | unsigned int detect_bus_select_failed; 100 | unsigned int detect_skip_disabled; 101 | unsigned int detect_skip_secondary; 102 | unsigned int detect_skip_found_on_bus_0; 103 | unsigned int detect_skip_duplicate_address; 104 | unsigned int detect_current_bus; 105 | i2c_sensor_t detect_current_sensor; 106 | 107 | uint64_t init_started_us; 108 | uint64_t init_finished_us; 109 | unsigned int init_started:1; 110 | unsigned int init_finished:1; 111 | unsigned int init_called; 112 | unsigned int init_bus_select_failed; 113 | unsigned int init_succeeded; 114 | unsigned int init_failed; 115 | unsigned int init_skipped; 116 | unsigned int init_current_sensor; 117 | 118 | unsigned int background_called; 119 | unsigned int background_succeeded; 120 | unsigned int background_failed; 121 | unsigned int background_bus_select_failed; 122 | unsigned int background_sensor_called; 123 | unsigned int background_wrapped; 124 | unsigned int background_current_sensor; 125 | unsigned int background_finished; 126 | } i2c_sensor_info_t; 127 | 128 | assert_size(i2c_sensor_info_t, 152); 129 | 130 | void i2c_sensor_get_info(i2c_sensor_info_t *); 131 | void i2c_sensors_periodic(void); 132 | bool i2c_sensor_read(string_t *, int bus, i2c_sensor_t, bool verbose, bool html); 133 | bool i2c_sensor_registered(int bus, i2c_sensor_t); 134 | void i2c_sensor_dump(bool verbose, string_t *dst); 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /stats.h: -------------------------------------------------------------------------------- 1 | #ifndef stats_h 2 | #define stats_h 3 | 4 | #include 5 | #include "dispatch.h" 6 | #include "util.h" 7 | 8 | enum 9 | { 10 | uarts = 2 11 | }; 12 | 13 | typedef struct 14 | { 15 | unsigned int user_pre_init_called:1; 16 | unsigned int user_pre_init_success:1; 17 | } stat_flags_t; 18 | 19 | extern stat_flags_t stat_flags; 20 | 21 | typedef struct 22 | { 23 | unsigned int rx_interrupts; 24 | unsigned int rx_posted; 25 | unsigned int rx_posted_max; 26 | unsigned int rx_posted_skipped; 27 | unsigned int tx_interrupts; 28 | unsigned int tx_posted; 29 | unsigned int tx_posted_max; 30 | unsigned int tx_posted_skipped; 31 | } stat_uart_instance_t; 32 | 33 | typedef struct 34 | { 35 | unsigned int spurious; 36 | 37 | stat_uart_instance_t instance[uarts]; 38 | } stat_uart_t; 39 | 40 | extern stat_uart_t stat_uart; 41 | 42 | extern unsigned int stat_fast_timer; 43 | extern unsigned int stat_slow_timer; 44 | extern unsigned int stat_pwm_cycles;; 45 | extern unsigned int stat_pwm_timer_interrupts; 46 | extern unsigned int stat_pwm_timer_interrupts_while_nmi_masked; 47 | extern unsigned int stat_pc_counts; 48 | extern unsigned int stat_renc_invalid_state; 49 | extern unsigned int stat_cmd_udp; 50 | extern unsigned int stat_cmd_tcp; 51 | extern unsigned int stat_cmd_uart; 52 | extern unsigned int stat_cmd_send_buffer_overflow; 53 | extern unsigned int stat_cmd_receive_buffer_overflow; 54 | extern unsigned int stat_cmd_udp_packet_incomplete; 55 | extern unsigned int stat_cmd_tcp_too_many_segments; 56 | extern unsigned int stat_cmd_invalid_packet_length; 57 | extern unsigned int stat_cmd_timeout; 58 | extern unsigned int stat_cmd_checksum_error; 59 | extern unsigned int stat_cmd_duplicate; 60 | extern unsigned int stat_uart_receive_buffer_overflow; 61 | extern unsigned int stat_uart_send_buffer_overflow; 62 | extern unsigned int stat_config_read_requests; 63 | extern unsigned int stat_config_read_loads; 64 | extern unsigned int stat_config_write_requests; 65 | extern unsigned int stat_config_write_saved; 66 | extern unsigned int stat_config_write_aborted; 67 | extern unsigned int stat_update_uart; 68 | extern unsigned int stat_update_longop; 69 | extern unsigned int stat_update_display; 70 | extern unsigned int stat_display_picture_load_worker_called; 71 | extern unsigned int stat_task_posted[task_prio_size]; 72 | extern unsigned int stat_task_executed[task_prio_size]; 73 | extern unsigned int stat_task_post_failed[task_prio_size]; 74 | extern unsigned int stat_task_current_queue[task_prio_size]; 75 | extern unsigned int stat_task_max_queue[task_prio_size]; 76 | extern unsigned int stat_lwip_tcp_send_error; 77 | extern unsigned int stat_lwip_udp_send_error; 78 | extern unsigned int stat_lwip_tcp_received_packets; 79 | extern unsigned int stat_lwip_udp_received_packets; 80 | extern unsigned int stat_lwip_tcp_received_bytes; 81 | extern unsigned int stat_lwip_udp_received_bytes; 82 | extern unsigned int stat_lwip_tcp_sent_packets; 83 | extern unsigned int stat_lwip_udp_sent_packets; 84 | extern unsigned int stat_lwip_tcp_sent_bytes; 85 | extern unsigned int stat_lwip_udp_sent_bytes; 86 | extern unsigned int stat_lwip_tcp_locked; 87 | extern unsigned int stat_lwip_udp_locked; 88 | extern unsigned int stat_lwip_unicast_received; 89 | extern unsigned int stat_lwip_broadcast_received; 90 | extern unsigned int stat_lwip_multicast_received; 91 | extern unsigned int stat_lwip_unicast_dropped; 92 | extern unsigned int stat_lwip_broadcast_dropped; 93 | extern unsigned int stat_lwip_multicast_dropped; 94 | extern unsigned int stat_broadcast_group_received; 95 | extern unsigned int stat_init_display_time_us; 96 | extern unsigned int stat_init_io_time_us; 97 | extern unsigned int stat_init_associate_time_us; 98 | extern unsigned int stat_init_ip_time_us; 99 | extern unsigned int stat_display_update_min_us; 100 | extern unsigned int stat_display_update_max_us; 101 | extern unsigned int stat_spi_slave_interrupts; 102 | extern unsigned int stat_spi_slave_i2s_interrupts; 103 | extern unsigned int stat_spi_largest_chunk; 104 | extern unsigned int stat_spi_wait_cycles; 105 | extern unsigned int stat_spi_8; 106 | extern unsigned int stat_spi_16; 107 | 108 | extern int stat_debug_1; 109 | extern int stat_debug_2; 110 | extern int stat_debug_3; 111 | 112 | extern unsigned int stat_i2c_init_time_us; 113 | extern unsigned int stat_i2c_sda_stucks; 114 | extern unsigned int stat_i2c_sda_stuck_max_period; 115 | extern unsigned int stat_i2c_bus_locks; 116 | extern unsigned int stat_i2c_bus_lock_max_period; 117 | extern unsigned int stat_i2c_soft_resets; 118 | extern unsigned int stat_i2c_hard_resets; 119 | 120 | extern unsigned int stat_font_render_time; 121 | 122 | extern unsigned int stat_heap_min, stat_heap_max; 123 | 124 | void stats_firmware(string_t *dst); 125 | void stats_flash(string_t *dst); 126 | void stats_time(string_t *dst); 127 | void stats_counters(string_t *dst); 128 | void stats_lwip(string_t *dst); 129 | void stats_i2c(string_t *dst); 130 | void stats_uart(string_t *dst); 131 | #endif 132 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/espconn_mdns.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright 2013-2014 Espressif Systems (Wuxi) 3 | * 4 | * FileName: espconn_mdns.c 5 | * 6 | * Description: udp proto interface 7 | * 8 | * Modification history: 9 | * 2014/3/31, v1.0 create this file. 10 | *******************************************************************************/ 11 | 12 | #include "ets_sys.h" 13 | #include "os_type.h" 14 | 15 | #include "lwip/mdns.h" 16 | 17 | /****************************************************************************** 18 | * FunctionName : espconn_mdns_enable 19 | * Description : join a multicast group 20 | * Parameters : host_ip -- the ip address of udp server 21 | * multicast_ip -- multicast ip given by user 22 | * Returns : none 23 | *******************************************************************************/ 24 | void ICACHE_FLASH_ATTR 25 | espconn_mdns_enable(void) 26 | { 27 | mdns_enable(); 28 | } 29 | /****************************************************************************** 30 | * FunctionName : espconn_mdns_disable 31 | * Description : join a multicast group 32 | * Parameters : host_ip -- the ip address of udp server 33 | * multicast_ip -- multicast ip given by user 34 | * Returns : none 35 | *******************************************************************************/ 36 | void ICACHE_FLASH_ATTR 37 | espconn_mdns_disable(void) 38 | { 39 | mdns_disable(); 40 | } 41 | 42 | /****************************************************************************** 43 | * FunctionName : espconn_mdns_set_hostname 44 | * Description : join a multicast group 45 | * Parameters : host_ip -- the ip address of udp server 46 | * multicast_ip -- multicast ip given by user 47 | * Returns : none 48 | *******************************************************************************/ 49 | void ICACHE_FLASH_ATTR 50 | espconn_mdns_set_hostname(char *name) 51 | { 52 | mdns_set_hostname(name); 53 | } 54 | 55 | /****************************************************************************** 56 | * FunctionName : espconn_mdns_init 57 | * Description : join a multicast group 58 | * Parameters : host_ip -- the ip address of udp server 59 | * multicast_ip -- multicast ip given by user 60 | * Returns : none 61 | *******************************************************************************/ 62 | char* ICACHE_FLASH_ATTR 63 | espconn_mdns_get_hostname(void) 64 | { 65 | return (char *)mdns_get_hostname(); 66 | } 67 | /****************************************************************************** 68 | * FunctionName : espconn_mdns_get_servername 69 | * Description : join a multicast group 70 | * Parameters : info -- the info of mdns 71 | * Returns : none 72 | *******************************************************************************/ 73 | void ICACHE_FLASH_ATTR 74 | espconn_mdns_set_servername(const char *name) 75 | { 76 | mdns_set_servername(name); 77 | } 78 | /****************************************************************************** 79 | * FunctionName : espconn_mdns_get_servername 80 | * Description : join a multicast group 81 | * Parameters : info -- the info of mdns 82 | * Returns : none 83 | *******************************************************************************/ 84 | char* ICACHE_FLASH_ATTR 85 | espconn_mdns_get_servername(void) 86 | { 87 | return (char *)mdns_get_servername(); 88 | } 89 | /****************************************************************************** 90 | * FunctionName : mdns_server_register 91 | * Description : join a multicast group 92 | * Parameters : info -- the info of mdns 93 | * Returns : none 94 | *******************************************************************************/ 95 | void ICACHE_FLASH_ATTR 96 | espconn_mdns_server_register(void) 97 | { 98 | mdns_server_register(); 99 | } 100 | /****************************************************************************** 101 | * FunctionName : mdns_server_register 102 | * Description : join a multicast group 103 | * Parameters : info -- the info of mdns 104 | * Returns : none 105 | *******************************************************************************/ 106 | void ICACHE_FLASH_ATTR 107 | espconn_mdns_server_unregister(void) 108 | { 109 | mdns_server_unregister(); 110 | } 111 | /****************************************************************************** 112 | * FunctionName : espconn_mdns_init 113 | * Description : join a multicast group 114 | * Parameters : host_ip -- the ip address of udp server 115 | * multicast_ip -- multicast ip given by user 116 | * Returns : none 117 | *******************************************************************************/ 118 | void ICACHE_FLASH_ATTR 119 | espconn_mdns_close(void) 120 | { 121 | mdns_close(); 122 | } 123 | /****************************************************************************** 124 | * FunctionName : espconn_mdns_init 125 | * Description : join a multicast group 126 | * Parameters : host_ip -- the ip address of udp server 127 | * multicast_ip -- multicast ip given by user 128 | * Returns : none 129 | *******************************************************************************/ 130 | void ICACHE_FLASH_ATTR 131 | espconn_mdns_init(struct mdns_info *info) 132 | { 133 | mdns_init(info); 134 | } 135 | -------------------------------------------------------------------------------- /remote_trigger.c: -------------------------------------------------------------------------------- 1 | #include "attribute.h" 2 | #include "application.h" 3 | #include "io.h" 4 | #include "remote_trigger.h" 5 | #include "lwip-interface.h" 6 | #include "config.h" 7 | #include "dispatch.h" 8 | 9 | enum 10 | { 11 | remote_trigger_local_udp_port = 1, 12 | remote_trigger_remote_udp_port = 24, 13 | remote_trigger_max_remotes = 2, 14 | }; 15 | 16 | typedef struct 17 | { 18 | union 19 | { 20 | unsigned int int_value; 21 | struct 22 | { 23 | unsigned int io:8; 24 | unsigned int pin:8; 25 | unsigned int index:8; 26 | io_trigger_t action:8; 27 | }; 28 | }; 29 | } remote_trigger_t; 30 | 31 | assert_size(remote_trigger_t, 4); 32 | 33 | string_new(static, remote_trigger_socket_send_buffer, 64); 34 | string_new(static, remote_trigger_socket_receive_buffer, 64); 35 | 36 | static lwip_if_socket_t trigger_socket; 37 | static ip_addr_t remote_trigger_address[remote_trigger_max_remotes]; 38 | static bool remote_trigger_active; 39 | 40 | static void socket_remote_trigger_callback_data_received(lwip_if_socket_t *socket, const lwip_if_callback_context_t *context) 41 | { 42 | string_clear(&remote_trigger_socket_receive_buffer); 43 | lwip_if_receive_buffer_unlock(socket, lwip_if_proto_all); 44 | } 45 | 46 | bool remote_trigger_init(void) 47 | { 48 | unsigned int remote_index; 49 | ip_addr_t remote_address; 50 | string_new(, ip, 32); 51 | 52 | remote_trigger_active = false; 53 | 54 | for(remote_index = 0; remote_index < remote_trigger_max_remotes; remote_index++) 55 | { 56 | if(config_get_string("trigger.remote.%u.%u", &ip, 0, remote_index) && !string_match_cstr(&ip, "0.0.0.0")) 57 | { 58 | remote_trigger_active = true; 59 | remote_address = ip_addr(string_to_cstr(&ip)); 60 | } 61 | else 62 | remote_address = ip_addr(0); 63 | 64 | remote_trigger_address[remote_index] = remote_address; 65 | } 66 | 67 | if(remote_trigger_active) 68 | lwip_if_socket_create(&trigger_socket, "trigger", &remote_trigger_socket_receive_buffer, &remote_trigger_socket_send_buffer, remote_trigger_local_udp_port, 69 | false, socket_remote_trigger_callback_data_received); 70 | 71 | return(true); 72 | } 73 | 74 | bool remote_trigger_add(unsigned int remote_index, unsigned int io, unsigned int pin, io_trigger_t action) 75 | { 76 | remote_trigger_t trigger; 77 | 78 | if(!remote_trigger_active) 79 | return(false); 80 | 81 | if(remote_index > remote_trigger_max_remotes) 82 | return(false); 83 | 84 | trigger.index = remote_index; 85 | trigger.io = io; 86 | trigger.pin = pin; 87 | trigger.action = action; 88 | 89 | dispatch_post_task(task_prio_medium, task_remote_trigger, trigger.int_value, 0, 0); 90 | 91 | return(true); 92 | } 93 | 94 | void remote_trigger_send(unsigned int argument) 95 | { 96 | const char *trigger_action = (char *)0; 97 | remote_trigger_t trigger; 98 | string_new(, ip, 32); 99 | 100 | if(!remote_trigger_active) 101 | return; 102 | 103 | if(lwip_if_send_buffer_locked(&trigger_socket)) 104 | { 105 | log("remote trigger send overflow\n"); 106 | return; 107 | } 108 | 109 | trigger.int_value = argument; 110 | 111 | if(trigger.index > remote_trigger_max_remotes) 112 | return; 113 | 114 | switch(trigger.action) 115 | { 116 | case(io_trigger_up): { trigger_action = "up"; break; } 117 | case(io_trigger_down): { trigger_action = "down"; break; } 118 | default: { return; } 119 | } 120 | 121 | string_clear(&remote_trigger_socket_send_buffer); 122 | string_format(&remote_trigger_socket_send_buffer, "it %u %u %s\n", trigger.io, trigger.pin, trigger_action); 123 | 124 | string_ip(&ip, remote_trigger_address[trigger.index]); 125 | 126 | if(!lwip_if_sendto(&trigger_socket, &remote_trigger_address[trigger.index], remote_trigger_remote_udp_port)) 127 | log("remote trigger send failed\n"); 128 | } 129 | 130 | app_action_t application_function_trigger_remote(app_params_t *parameters) 131 | { 132 | unsigned int remote_index; 133 | string_new(, remote_ip, 32); 134 | 135 | if(parse_uint(1, parameters->src, &remote_index, 0, ' ') != parse_ok) 136 | { 137 | string_format(parameters->dst, "usage: io-trigger-remote [ip address of remote]\n", remote_trigger_max_remotes - 1); 138 | return(app_action_error); 139 | } 140 | 141 | if(remote_index >= remote_trigger_max_remotes) 142 | { 143 | string_format(parameters->dst, "index must be [0 - %d]\n", remote_trigger_max_remotes - 1); 144 | return(app_action_error); 145 | } 146 | 147 | if(parse_string(2, parameters->src, &remote_ip, ' ') == parse_ok) 148 | { 149 | if(!config_open_write()) 150 | { 151 | string_append(parameters->dst, "cannot set config (open)\n"); 152 | return(app_action_error); 153 | } 154 | 155 | config_delete("trigger.remote.%u.%u", false, 0, remote_index); 156 | 157 | if(!string_match_cstr(&remote_ip, "0.0.0.0")) 158 | { 159 | if(!config_set_string("trigger.remote.%u.%u", string_to_cstr(&remote_ip), 0, remote_index)) 160 | { 161 | config_abort_write(); 162 | string_append(parameters->dst, "cannot set config\n"); 163 | return(app_action_error); 164 | } 165 | } 166 | 167 | if(!config_close_write()) 168 | { 169 | string_append(parameters->dst, "cannot set config (close)\n"); 170 | return(app_action_error); 171 | } 172 | } 173 | 174 | string_clear(&remote_ip); 175 | if(!config_get_string("trigger.remote.%u.%u", &remote_ip, 0, remote_index)) 176 | { 177 | string_clear(&remote_ip); 178 | string_append(&remote_ip, ""); 179 | } 180 | 181 | string_format(parameters->dst, "io-trigger-remote: index: %u, server: %s\n", remote_index, string_to_cstr(&remote_ip)); 182 | 183 | return(app_action_normal); 184 | } 185 | 186 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/include/mdns.h: -------------------------------------------------------------------------------- 1 | /** 2 | * lwip MDNS resolver header file. 3 | * 4 | * Created on: Jul 29, 2010 5 | * Author: Daniel Toma 6 | 7 | 8 | * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. The name of the author may not be used to endorse or promote 19 | * products derived from this software without specific prior 20 | * written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 26 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 28 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef __LWIP_MDNS_H__ 36 | #define __LWIP_MDNS_H__ 37 | 38 | #include "lwip/opt.h" 39 | 40 | #if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */ 41 | 42 | /** DNS timer period */ 43 | #define DNS_TMR_INTERVAL 1000 44 | 45 | /** mDNS Address offset flag*/ 46 | #define DNS_OFFSET_FLAG 0xC0 /* the offset flag in the DNS message */ 47 | #define DNS_DEFAULT_OFFSET 0x0C /* the offset is set at the beginning of the DNS message */ 48 | 49 | #define DNS_IP_ADDR_LEN 4 50 | 51 | 52 | /** DNS field TYPE used for "Resource Records" */ 53 | #define DNS_RRTYPE_A 1 /* a host address */ 54 | #define DNS_RRTYPE_NS 2 /* an authoritative name server */ 55 | #define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ 56 | #define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ 57 | #define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ 58 | #define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ 59 | #define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ 60 | #define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ 61 | #define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ 62 | #define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ 63 | #define DNS_RRTYPE_WKS 11 /* a well known service description */ 64 | #define DNS_RRTYPE_PTR 12 /* a domain name pointer */ 65 | #define DNS_RRTYPE_HINFO 13 /* host information */ 66 | #define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ 67 | #define DNS_RRTYPE_MX 15 /* mail exchange */ 68 | #define DNS_RRTYPE_TXT 16 /* text strings */ 69 | #define DNS_RRTYPE_SRV 33 /* Service record */ 70 | #define DNS_RRTYPE_OPT 41 /* EDNS0 OPT record */ 71 | #define DNS_RRTYPE_TSIG 250 /* Transaction Signature */ 72 | #define DNS_RRTYPE_ANY 255 /*Not a DNS type, but a DNS query type, meaning "all types"*/ 73 | 74 | /* DNS field CLASS used for "Resource Records" */ 75 | #define DNS_RRCLASS_IN 1 /* the Internet */ 76 | #define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ 77 | #define DNS_RRCLASS_CH 3 /* the CHAOS class */ 78 | #define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ 79 | #define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ 80 | #define DNS_RRCLASS_FLUSH_IN 0x8001/* Flush bit and Internet*/ 81 | 82 | /** Callback which is invoked when a hostname is found. 83 | * A function of this type must be implemented by the application using the DNS resolver. 84 | * @param name pointer to the name that was looked up. 85 | * @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname, 86 | * or NULL if the name could not be found (or on any other error). 87 | * @param callback_arg a user-specified callback argument passed to dns_gethostbyname 88 | */ 89 | #ifndef _MDNS_INFO 90 | #define _MDNS_INFO 91 | struct mdns_info { 92 | char *host_name; 93 | char *server_name; 94 | uint16 server_port; 95 | unsigned long ipAddr; 96 | char *txt_data[10]; 97 | }; 98 | #endif 99 | //void mdns_enable(void); 100 | //void mdns_disable(void); 101 | //void mdns_init(struct mdns_info *info); 102 | //void mdns_close(void); 103 | //char* mdns_get_hostname(void); 104 | //void mdns_set_hostname(char *name); 105 | //void mdns_set_servername(const char *name); 106 | //char* mdns_get_servername(void); 107 | //void mdns_server_unregister(void); 108 | //void mdns_server_register(void) ; 109 | //void mdns_tmr(void); 110 | //void Delay(unsigned long ulSeconds); 111 | 112 | #endif /* LWIP_DNS */ 113 | 114 | #endif /* __LWIP_DNS_H__ */ 115 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/espconn_buf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * espconn_buf.c 3 | * 4 | * Created on: May 25, 2016 5 | * Author: liuhan 6 | */ 7 | 8 | #include "lwip/memp.h" 9 | #include "lwip/def.h" 10 | #include "ets_sys.h" 11 | #include "os_type.h" 12 | #include "lwip/app/espconn_buf.h" 13 | 14 | 15 | #ifdef MEMLEAK_DEBUG 16 | static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; 17 | #endif 18 | 19 | #if (!defined(lwIP_unlikely)) 20 | #define lwIP_unlikely(Expression) !!(Expression) 21 | #endif 22 | 23 | #define lwIP_ASSERT(Expression) do{if(!(Expression)) {os_printf("%s %d\n", __func__, __LINE__);return 0;}}while(0) 24 | #define lwIP_ASSERTS(Expression) do{if(!(Expression)) {os_printf("%s %d\n", __func__, __LINE__);return;}}while(0) 25 | 26 | ringbuf_t ICACHE_FLASH_ATTR 27 | ringbuf_new(size_t capacity) 28 | { 29 | ringbuf_t rb = (ringbuf_t)os_zalloc(sizeof(struct ringbuf_t)); 30 | if (rb){ 31 | rb->size = capacity + 1; 32 | rb->buf = (uint8*)os_zalloc(rb->size); 33 | if (rb->buf){ 34 | ringbuf_reset(rb); 35 | }else{ 36 | os_free(rb); 37 | return NULL; 38 | } 39 | } 40 | return rb; 41 | } 42 | 43 | size_t ICACHE_FLASH_ATTR 44 | ringbuf_buffer_size(const struct ringbuf_t *rb) 45 | { 46 | return rb->size; 47 | } 48 | 49 | void ICACHE_FLASH_ATTR 50 | ringbuf_reset(ringbuf_t rb) 51 | { 52 | rb ->head = rb->tail = rb->buf; 53 | } 54 | 55 | void ICACHE_FLASH_ATTR 56 | ringbuf_free(ringbuf_t *rb) 57 | { 58 | lwIP_ASSERTS(rb && *rb); 59 | os_free((*rb)->buf); 60 | os_free(*rb); 61 | *rb = NULL; 62 | } 63 | 64 | size_t ICACHE_FLASH_ATTR 65 | ringbuf_capacity(const struct ringbuf_t *rb) 66 | { 67 | return ringbuf_buffer_size(rb) - 1; 68 | } 69 | 70 | static const uint8_t* ICACHE_FLASH_ATTR 71 | ringbuf_end(const struct ringbuf_t *rb) 72 | { 73 | return rb->buf + ringbuf_buffer_size(rb); 74 | } 75 | 76 | size_t ICACHE_FLASH_ATTR 77 | ringbuf_bytes_free(const struct ringbuf_t *rb) 78 | { 79 | if (rb->head >= rb->tail){ 80 | return ringbuf_capacity(rb) - (rb->head - rb->tail); 81 | }else{ 82 | return rb->tail - rb->head -1; 83 | } 84 | } 85 | 86 | size_t ICACHE_FLASH_ATTR 87 | ringbuf_bytes_used(const struct ringbuf_t *rb) 88 | { 89 | return ringbuf_capacity(rb) - ringbuf_bytes_free(rb); 90 | } 91 | 92 | int ICACHE_FLASH_ATTR 93 | ringbuf_is_full(const struct ringbuf_t *rb) 94 | { 95 | return ringbuf_bytes_free(rb) == 0; 96 | } 97 | 98 | int ICACHE_FLASH_ATTR 99 | ringbuf_is_empty(const struct ringbuf_t *rb) 100 | { 101 | return ringbuf_bytes_free(rb) == ringbuf_capacity(rb); 102 | } 103 | 104 | const void* ICACHE_FLASH_ATTR 105 | ringbuf_tail(const struct ringbuf_t *rb) 106 | { 107 | return rb->tail; 108 | } 109 | const void* ICACHE_FLASH_ATTR 110 | ringbuf_head(const struct ringbuf_t *rb) 111 | { 112 | return rb->head; 113 | } 114 | 115 | static uint8_t* ICACHE_FLASH_ATTR 116 | ringbuf_nextp(ringbuf_t rb, const uint8_t *p) 117 | { 118 | lwIP_ASSERT((p >= rb->buf) && (p < ringbuf_end(rb))); 119 | return rb->buf + ((++p -rb->buf) % ringbuf_buffer_size(rb)); 120 | } 121 | 122 | size_t ICACHE_FLASH_ATTR 123 | ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset) 124 | { 125 | const uint8_t *bufend = ringbuf_end(rb); 126 | size_t bytes_used = ringbuf_bytes_used(rb); 127 | if (offset >= bytes_used) 128 | return bytes_used; 129 | 130 | const uint8_t *start = rb ->buf + (((rb->tail - rb->buf) + offset) % ringbuf_buffer_size(rb)); 131 | lwIP_ASSERT(bufend > start); 132 | size_t n = LWIP_MIN(bufend - start, bytes_used - offset); 133 | const uint8_t *found = (const uint8_t *)memchr(start, c, n); 134 | if (found) 135 | return offset + (found - start); 136 | else 137 | return ringbuf_findchr(rb, c, offset + n); 138 | } 139 | 140 | size_t ICACHE_FLASH_ATTR 141 | ringbuf_memset(ringbuf_t dst, int c, size_t len) 142 | { 143 | const uint8_t *bufend = ringbuf_end(dst); 144 | size_t nwritten = 0; 145 | size_t count = LWIP_MIN(len, ringbuf_buffer_size(dst)); 146 | int overflow = count > ringbuf_bytes_free(dst); 147 | 148 | while (nwritten != count){ 149 | 150 | lwIP_ASSERT(bufend > dst->head); 151 | size_t n = LWIP_MIN(bufend - dst->head, count - nwritten); 152 | os_memset(dst->head, c, n); 153 | dst->head += n; 154 | nwritten += n; 155 | 156 | if (dst->head == bufend) 157 | dst->head = dst->buf; 158 | } 159 | 160 | if (overflow){ 161 | dst->tail = ringbuf_nextp(dst, dst->head); 162 | lwIP_ASSERT(ringbuf_is_full(dst)); 163 | } 164 | 165 | return nwritten; 166 | } 167 | 168 | void* ICACHE_FLASH_ATTR 169 | ringbuf_memcpy_into(ringbuf_t dst,const void *src, size_t count) 170 | { 171 | const uint8_t *u8src = src; 172 | const uint8_t *bufend = ringbuf_end(dst); 173 | int overflow = count > ringbuf_bytes_free(dst); 174 | size_t nread = 0; 175 | 176 | while (nread != count){ 177 | lwIP_ASSERT(bufend > dst->head); 178 | size_t n = LWIP_MIN(bufend - dst->head, count - nread); 179 | os_memcpy(dst->head, u8src + nread, n); 180 | dst->head += n; 181 | nread += n; 182 | 183 | if (dst->head == bufend) 184 | dst->head = dst->buf; 185 | } 186 | 187 | if (overflow) { 188 | dst->tail = ringbuf_nextp(dst, dst->head); 189 | lwIP_ASSERT(ringbuf_is_full(dst)); 190 | } 191 | 192 | return dst->head; 193 | } 194 | 195 | void* ICACHE_FLASH_ATTR 196 | ringbuf_memcpy_from(void *dst,ringbuf_t src, size_t count) 197 | { 198 | size_t bytes_used = ringbuf_bytes_used(src); 199 | 200 | if (count > bytes_used) 201 | return NULL; 202 | 203 | const uint8_t *u8dst = dst; 204 | const uint8_t *bufend = ringbuf_end(src); 205 | size_t nwritten = 0; 206 | 207 | while (nwritten != count){ 208 | lwIP_ASSERT(bufend > src->tail); 209 | size_t n = LWIP_MIN(bufend - src->tail, count - nwritten); 210 | os_memcpy((uint8_t*)u8dst + nwritten, src->tail, n); 211 | src->tail += n; 212 | nwritten += n; 213 | 214 | if (src->tail == bufend) 215 | src->tail = src->buf; 216 | } 217 | 218 | lwIP_ASSERT(count + ringbuf_bytes_used(src) == bytes_used); 219 | return src->tail; 220 | } 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /symboltable.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | no warnings 'portable'; 4 | 5 | use Data::Dumper; 6 | 7 | my($input) = $ARGV[0]; 8 | my($fd); 9 | my($symbol, $address, $class, $type, $size, $line, $section, $source); 10 | my(%symbols, %value); 11 | 12 | my(%sections) = ( 13 | "bss" => 14 | { 15 | "data" => 1, 16 | "start" => hex("3ffe8000"), 17 | "end" => hex("3fffbfff"), 18 | }, 19 | "data" => 20 | { 21 | "data" => 1, 22 | "start" => hex("3ffe8000"), 23 | "end" => hex("3fffbfff"), 24 | }, 25 | "irom0.text" => 26 | { 27 | "data" => 0, 28 | "start" => hex("0x40200000"), 29 | "end" => hex("0x402fa000"), 30 | }, 31 | "rodata" => 32 | { 33 | "data" => 1, 34 | "start" => hex("0x3ffe8000"), 35 | "end" => hex("0x3fffbfff"), 36 | }, 37 | "text" => 38 | { 39 | "data" => 0, 40 | "start" => hex("0x40100000"), 41 | "end" => hex("0x40108000"), 42 | }, 43 | ); 44 | 45 | my(%class_to_text) = ( 46 | "A" => "global absolute", 47 | "a" => "local absolute", 48 | "B" => "global bss", 49 | "b" => "local bss", 50 | "C" => "common", 51 | "D" => "global data", 52 | "d" => "local data", 53 | "G" => "global sdata", 54 | "g" => "local sdata", 55 | "I" => "indirect", 56 | "N" => "debug", 57 | "n" => "comment", 58 | "p" => "stack unwind", 59 | "R" => "global rodata", 60 | "r" => "local rodata", 61 | "S" => "global sbbs", 62 | "s" => "local sbbs", 63 | "T" => "global text", 64 | "t" => "local text", 65 | "U" => "undefined", 66 | "u" => "unique", 67 | "V" => "WEAK1", 68 | "v" => "weak1", 69 | "W" => "WEAK2", 70 | "w" => "weak2", 71 | "-" => "stab", 72 | "?" => "unknown", 73 | "" => "", 74 | ); 75 | 76 | die("failed to start nm") if(!open($fd, "nm -n -l -a -fsysv --synthetic " . $input . " |")); 77 | 78 | while(<$fd>) 79 | { 80 | chomp(); 81 | 82 | ($symbol, $address, $class, $type, $size, $line, $section, $source) = 83 | m/^([^\s|]+)\s*\|\s*([0-9a-f]+)\s*\|\s*([^\s]+)\s*\|\s*([^\s|]*)\s*\|\s*([0-9a-f]*)\s*\|\s*([\^s|]*)\s*\|\s*([a-zA-Z0-9._*]*)\s*(.*)$/o; 84 | 85 | next if(!defined($symbol) || !defined($address) || !defined($class) || !defined($type) || !defined($size) || !defined($line) || !defined($section) || !defined($source)); 86 | next if($section !~ m/^\.[a-zA-Z]+/g); 87 | 88 | $section =~ s/^.//o; 89 | 90 | undef(%value); 91 | $value{name} = $symbol; 92 | $value{address} = hex($address); 93 | $value{size_1} = hex($size); 94 | $value{class} = $class; 95 | $value{type} = $type; 96 | ($value{source_file}, $value{source_line}) = $source =~ m/\/([^\/]+):([0-9]+)$/o; 97 | 98 | %{$symbols{section}{$section}{by_name}{$symbol}} = %value; 99 | %{$symbols{section}{$section}{by_address}{hex($address)}} = %value; 100 | } 101 | 102 | close($fd); 103 | 104 | my($sections_entry, $previous_address, $this_address, $previous, $this, $key); 105 | 106 | for $section (sort(keys(%{$symbols{section}}))) 107 | { 108 | undef($previous_address); 109 | 110 | if(!exists($sections{$section})) 111 | { 112 | printf("section %s is unknown\n", $section); 113 | next; 114 | } 115 | 116 | $sections_entry = \%{$sections{$section}}; 117 | $$sections_entry{size_1} = 0; 118 | $$sections_entry{size_2} = 0; 119 | 120 | for $this_address (sort(keys(%{$symbols{section}{$section}{by_address}}))) 121 | { 122 | if(!defined($previous_address)) 123 | { 124 | $previous_address = $this_address; 125 | next; 126 | } 127 | 128 | $previous = \%{$symbols{section}{$section}{by_address}{$previous_address}}; 129 | $this = \%{$symbols{section}{$section}{by_address}{$this_address}}; 130 | 131 | if(($$this{address} < $$sections_entry{start}) || ($$this{address} > $$sections_entry{end})) 132 | { 133 | printf(" invalid address for symbol %s for section %s: %x\n", $$this{name}, $section, $$this{address}); 134 | next; 135 | } 136 | 137 | $$previous{size_2} = $$this{address} - $$previous{address}; 138 | $$sections_entry{size_1} += $$previous{size_1}; 139 | $$sections_entry{size_2} += $$previous{size_2}; 140 | $key = sprintf("%-10s:%4x:%s", $section, $$previous{size_1}, $$previous{address}); 141 | %{$symbols{section}{$section}{by_size}{$key}} = %{$previous}; 142 | 143 | $previous_address = $this_address; 144 | } 145 | 146 | $$this{size_2} = $$this{size_1}; 147 | $$sections_entry{size_1} += $$this{size_1}; 148 | $$sections_entry{size_2} += $$this{size_1}; 149 | 150 | $key = sprintf("%-10s:%4x:%s", $section, $$this{size_1}, $$this{address}); 151 | %{$symbols{section}{$section}{by_size}{$key}} = %{$this}; 152 | } 153 | 154 | my(%section_to_region) = 155 | ( 156 | "bss" => "dram", 157 | "data" => "dram", 158 | "rodata" => "dram", 159 | "text" => "iram", 160 | "irom0.text" => "flash", 161 | ); 162 | 163 | my($region, %region); 164 | 165 | printf("sections\n"); 166 | 167 | for $section (qw[bss data rodata text irom0.text]) 168 | { 169 | $region = $section_to_region{$section}; 170 | 171 | printf(" %-10s used: %6d region: %s\n", 172 | $section, 173 | $sections{$section}{size_2}, 174 | $region); 175 | 176 | $region{$region}{name} = $region; 177 | $region{$region}{start} = $sections{$section}{start}; 178 | $region{$region}{end} = $sections{$section}{end}; 179 | $region{$region}{size} += $sections{$section}{size_2}; 180 | } 181 | 182 | printf("\nregions\n"); 183 | 184 | my($length); 185 | 186 | for $region (qw[dram iram flash]) 187 | { 188 | $length = $region{$region}{end} - $region{$region}{start}; 189 | $free = $length - $region{$region}{size}; 190 | 191 | printf(" %-10s start: 0x%8x end: 0x%8x length: %7d used: %6d free: %6d %3d%%\n", 192 | $region, 193 | $region{$region}{start}, 194 | $region{$region}{end}, 195 | $length, 196 | $region{$region}{size}, 197 | $free, 198 | ($free * 100) / $length, 199 | ); 200 | } 201 | 202 | printf("\nsymbols\n"); 203 | 204 | my($name, $section2, $source_line, $source_file); 205 | 206 | printf(" %-10s %-6s %-14s %-8s %-5s %-5s %-44s %-4s %s\n", "section", "region", "class", "address", "size1", "size2", "name", "line", "file"); 207 | 208 | for $section (qw[bss data rodata text irom0.text]) 209 | { 210 | $region = $section_to_region{$section}; 211 | 212 | for $key (sort(keys(%{$symbols{section}{$section}{by_size}}))) 213 | { 214 | ($section2, $size, $address) = $key =~ m/^([^\s]+)\s*:\s*([0-9a-f]+)\s*:(.*)/o; 215 | 216 | $this = \%{$symbols{section}{$section}{by_address}{$address}}; 217 | 218 | $source_line = $$this{source_line}; 219 | $source_file = $$this{source_file}; 220 | 221 | $source_file = "" if(!defined($source_file)); 222 | 223 | if(!defined($source_line)) 224 | { 225 | $source_line = ""; 226 | } 227 | else 228 | { 229 | $source_line = sprintf("%4s", $source_line); 230 | } 231 | 232 | printf(" %-10s %-6s %-14s %08x %5d %5d %-44s %-4s %s\n", $section2, $region, $class_to_text{$$this{class}}, $address, $$this{size_1}, $$this{size_2}, 233 | $$this{name}, $source_line, $source_file); 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /io_aux.c: -------------------------------------------------------------------------------- 1 | #include "io_aux.h" 2 | 3 | #include "io_gpio.h" 4 | #include "dispatch.h" 5 | #include "util.h" 6 | 7 | #include 8 | 9 | static attr_const io_error_t init(const struct io_info_entry_T *info) 10 | { 11 | return(io_ok); 12 | } 13 | 14 | static attr_pure unsigned int pin_max_value(const struct io_info_entry_T *info, io_data_pin_entry_t *data, const io_config_pin_entry_t *pin_config, unsigned int pin) 15 | { 16 | unsigned int value = 0; 17 | 18 | switch(pin_config->llmode) 19 | { 20 | case(io_pin_ll_input_digital): 21 | case(io_pin_ll_output_digital): 22 | { 23 | value = 0x01; 24 | break; 25 | } 26 | 27 | case(io_pin_ll_input_analog): 28 | { 29 | value = 0x400; 30 | break; 31 | } 32 | 33 | default: 34 | break; 35 | } 36 | 37 | return(value); 38 | } 39 | 40 | static io_error_t init_pin_mode(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin) 41 | { 42 | switch(pin) 43 | { 44 | case(io_aux_pin_gpio): 45 | { 46 | switch(pin_config->llmode) 47 | { 48 | case(io_pin_ll_disabled): 49 | { 50 | break; 51 | } 52 | 53 | case(io_pin_ll_input_digital): 54 | { 55 | clear_set_peri_reg_mask(PAD_XPD_DCDC_CONF, 0x43, 0x01); 56 | clear_set_peri_reg_mask(RTC_GPIO_CONF, 0x01, 0x00); 57 | clear_set_peri_reg_mask(RTC_GPIO_ENABLE, 0x01, 0x00); 58 | 59 | break; 60 | } 61 | 62 | case(io_pin_ll_output_digital): 63 | { 64 | clear_set_peri_reg_mask(PAD_XPD_DCDC_CONF, 0x43, 0x01); 65 | clear_set_peri_reg_mask(RTC_GPIO_CONF, 0x01, 0x00); 66 | clear_set_peri_reg_mask(RTC_GPIO_ENABLE, 0x01, 0x01); 67 | 68 | break; 69 | } 70 | 71 | default: 72 | { 73 | if(error_message) 74 | string_append(error_message, "invalid mode for this pin\n"); 75 | 76 | return(io_error); 77 | } 78 | } 79 | 80 | break; 81 | } 82 | 83 | case(io_aux_pin_adc): 84 | { 85 | switch(pin_config->llmode) 86 | { 87 | case(io_pin_ll_input_analog): 88 | { 89 | break; 90 | } 91 | 92 | default: 93 | { 94 | if(error_message) 95 | string_append(error_message, "invalid mode for this pin\n"); 96 | 97 | return(io_error); 98 | } 99 | 100 | } 101 | 102 | break; 103 | } 104 | 105 | default: 106 | { 107 | if(error_message) 108 | string_append(error_message, "invalid mode for this io\n"); 109 | 110 | return(io_error); 111 | } 112 | } 113 | 114 | return(io_ok); 115 | } 116 | 117 | static io_error_t get_pin_info(string_t *dst, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin) 118 | { 119 | switch(pin) 120 | { 121 | case(io_aux_pin_gpio): 122 | { 123 | string_format(dst, "builtin rtc gpio, state: %s", onoff(read_peri_reg(RTC_GPIO_IN_DATA) & 0x01)); 124 | break; 125 | } 126 | 127 | case(io_aux_pin_adc): 128 | { 129 | string_append(dst, "builtin adc input"); 130 | break; 131 | } 132 | 133 | default: 134 | { 135 | string_append(dst, "invalid mode for this io\n"); 136 | return(io_error); 137 | } 138 | } 139 | 140 | return(io_ok); 141 | } 142 | 143 | iram static io_error_t read_pin(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin, unsigned int *value) 144 | { 145 | switch(pin) 146 | { 147 | case(io_aux_pin_gpio): 148 | { 149 | switch(pin_config->llmode) 150 | { 151 | case(io_pin_ll_input_digital): 152 | case(io_pin_ll_output_digital): 153 | { 154 | *value = !!(read_peri_reg(RTC_GPIO_IN_DATA) & 0x01); 155 | 156 | if(pin_config->static_flags & io_flag_static_invert) 157 | *value = !*value; 158 | 159 | break; 160 | } 161 | 162 | default: 163 | { 164 | if(error_message) 165 | string_append(error_message, "invalid mode for this pin\n"); 166 | return(io_error); 167 | } 168 | } 169 | 170 | break; 171 | } 172 | 173 | case(io_aux_pin_adc): 174 | { 175 | switch(pin_config->llmode) 176 | { 177 | case(io_pin_ll_input_analog): 178 | { 179 | *value = system_adc_read() << 6; 180 | 181 | break; 182 | } 183 | 184 | default: 185 | { 186 | if(error_message) 187 | string_append(error_message, "invalid mode for this pin\n"); 188 | 189 | return(io_error); 190 | } 191 | 192 | } 193 | 194 | break; 195 | } 196 | 197 | default: 198 | { 199 | if(error_message) 200 | string_append(error_message, "invalid pin for this io\n"); 201 | 202 | return(io_error); 203 | } 204 | } 205 | 206 | return(io_ok); 207 | } 208 | 209 | iram static io_error_t write_pin(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin, unsigned int value) 210 | { 211 | switch(pin) 212 | { 213 | case(io_aux_pin_gpio): 214 | { 215 | switch(pin_config->llmode) 216 | { 217 | case(io_pin_ll_input_digital): 218 | { 219 | if(error_message) 220 | string_append(error_message, "cannot write to input\n"); 221 | return(io_error); 222 | } 223 | 224 | case(io_pin_ll_output_digital): 225 | { 226 | if(pin_config->static_flags & io_flag_static_invert) 227 | value = !value; 228 | 229 | clear_set_peri_reg_mask(RTC_GPIO_OUT, 0x01, value ? 0x01 : 0x00); 230 | break; 231 | } 232 | 233 | default: 234 | { 235 | if(error_message) 236 | string_append(error_message, "invalid mode for this pin\n"); 237 | 238 | return(io_error); 239 | } 240 | 241 | } 242 | 243 | break; 244 | } 245 | 246 | case(io_aux_pin_adc): 247 | { 248 | switch(pin_config->llmode) 249 | { 250 | case(io_pin_ll_input_analog): 251 | { 252 | if(error_message) 253 | string_append(error_message, "cannot write to adc\n"); 254 | 255 | return(io_error); 256 | } 257 | 258 | default: 259 | { 260 | if(error_message) 261 | string_append(error_message, "invalid mode for this pin\n"); 262 | 263 | return(io_error); 264 | } 265 | 266 | } 267 | 268 | break; 269 | } 270 | 271 | default: 272 | { 273 | if(error_message) 274 | string_append(error_message, "invalid pin for this io\n"); 275 | 276 | return(io_error); 277 | } 278 | } 279 | 280 | return(io_ok); 281 | } 282 | 283 | roflash const io_info_entry_t io_info_entry_aux = 284 | { 285 | io_id_aux,/* = 1 */ 286 | 0x01, 287 | 0, 288 | 2, 289 | caps_input_digital | 290 | caps_output_digital | 291 | caps_input_analog, 292 | "Auxilliary GPIO (RTC+ADC)", 293 | init, 294 | (void *)0, // postinit 295 | pin_max_value, 296 | (void *)0, // periodic slow 297 | (void *)0, // periodic fast 298 | (void *)0, // pin change handler 299 | init_pin_mode, 300 | get_pin_info, 301 | read_pin, 302 | write_pin, 303 | (void *)0, // set_mask 304 | }; 305 | -------------------------------------------------------------------------------- /i2s.c: -------------------------------------------------------------------------------- 1 | #include "i2s.h" 2 | #include "util.h" 3 | #include "io.h" 4 | #include "eagle.h" 5 | #include "io_gpio.h" 6 | #include "stats.h" 7 | 8 | #include 9 | 10 | static bool inited = false; 11 | 12 | enum 13 | { 14 | bits_per_sample = 4, 15 | values_per_led = 4, /* some LEDs take four values */ 16 | }; 17 | 18 | attr_inline void i2s_interrupt_arm(bool enable) // inline required for ISR in IRAM 19 | { 20 | static const unsigned int all_i2s_ints_clear = 21 | I2S_I2S_TX_REMPTY_INT_CLR | 22 | I2S_I2S_TX_WFULL_INT_CLR | 23 | I2S_I2S_RX_REMPTY_INT_CLR | 24 | I2S_I2S_RX_WFULL_INT_CLR | 25 | I2S_I2S_PUT_DATA_INT_CLR | 26 | I2S_I2S_TAKE_DATA_INT_CLR; 27 | 28 | clear_peri_reg_mask(I2SINT_ENA, all_i2s_ints_clear); 29 | set_peri_reg_mask(I2SINT_CLR, all_i2s_ints_clear); 30 | clear_peri_reg_mask(I2SINT_CLR, all_i2s_ints_clear); 31 | 32 | if(enable) 33 | set_peri_reg_mask(I2SINT_ENA, I2S_I2S_TX_REMPTY_INT_ENA); 34 | } 35 | 36 | iram static void i2s_callback(void *arg) 37 | { 38 | ets_isr_mask(1 << ETS_SPI_INUM); 39 | 40 | stat_spi_slave_interrupts++; 41 | 42 | if(!(read_peri_reg(ISR_FLAGS_REG) & ISR_FLAGS_I2S)) 43 | goto done; 44 | 45 | stat_spi_slave_i2s_interrupts++; 46 | i2s_interrupt_arm(false); 47 | clear_peri_reg_mask(I2SCONF, I2S_I2S_TX_START); 48 | 49 | done: 50 | ets_isr_unmask(1 << ETS_SPI_INUM); 51 | } 52 | 53 | /* 54 | * Espressif black magic. No clue how it works, so please don't ask. 55 | */ 56 | 57 | static unsigned int get_peri_reg_bits(unsigned int reg, unsigned int hipos, unsigned int lowpos) 58 | { 59 | return((read_peri_reg(reg) >> lowpos) & ((1 << (hipos - lowpos + 1)) - 1)); 60 | } 61 | 62 | static unsigned int espressif_opaque_i2c_readReg(unsigned int block, unsigned int host_id, unsigned int reg_add) 63 | { 64 | uint32_t mst_ctrl_addr = 0x60000d00 + (host_id * 4); 65 | 66 | write_peri_reg(mst_ctrl_addr, (0 << 24) | (0 << 16) | (reg_add << 8) | block); 67 | while(get_peri_reg_bits(mst_ctrl_addr, 25, 25) != 0); 68 | return((read_peri_reg(mst_ctrl_addr) >> 16) & 0xff); 69 | } 70 | 71 | static void espressif_opaque_i2c_writeReg(unsigned int block, unsigned int host_id, unsigned int reg_add, unsigned int pData) 72 | { 73 | uint32_t mst_ctrl_addr = 0x60000d00 + (host_id * 4); 74 | 75 | write_peri_reg(mst_ctrl_addr, (1 << 24) | (pData << 16) | (reg_add << 8) | block); 76 | while(get_peri_reg_bits(mst_ctrl_addr, 25, 25) != 0); 77 | } 78 | 79 | static void espressif_opaque_i2c_writeReg_Mask(unsigned int block, unsigned int host_id, unsigned int reg_add, unsigned int msb, unsigned int lsb, unsigned int indata) 80 | { 81 | unsigned int current = espressif_opaque_i2c_readReg(block, host_id, reg_add); 82 | 83 | espressif_opaque_i2c_writeReg(block, host_id, reg_add, (current & (~(((1 << (msb - lsb + 1)) - 1) << lsb))) | (indata << lsb)); 84 | } 85 | 86 | static void espressif_opaque_start_i2s_clock(void) 87 | { 88 | espressif_opaque_i2c_writeReg_Mask(0x67, 0x04, 0x04, 0x07, 0x07, 0x01); 89 | } 90 | 91 | /* https://github.com/espressif/ESP8266_MP3_DECODER/issues/3 92 | * 93 | * CLK_I2S = 160MHz / I2S_CLKM_DIV_NUM 94 | * BCLK = CLK_I2S / I2S_BCK_DIV_NUM 95 | * WS = BCLK / 2 / (16 + I2S_BITS_MOD) 96 | * Note that I2S_CLKM_DIV_NUM must be >5 for I2S data */ 97 | 98 | bool i2s_init(void) 99 | { 100 | static const unsigned int all_spi_slave_ints = 101 | SPI_TRANS_DONE_EN | 102 | SPI_SLV_WR_STA_DONE_EN | 103 | SPI_SLV_RD_STA_DONE_EN | 104 | SPI_SLV_WR_BUF_DONE_EN | 105 | SPI_SLV_RD_BUF_DONE_EN | 106 | SPI_TRANS_DONE | 107 | SPI_SLV_WR_STA_DONE | 108 | SPI_SLV_RD_STA_DONE | 109 | SPI_SLV_WR_BUF_DONE | 110 | SPI_SLV_RD_BUF_DONE; 111 | 112 | static const unsigned int conf_reset_mask = I2S_I2S_TX_FIFO_RESET | I2S_I2S_RX_FIFO_RESET | I2S_I2S_TX_RESET | I2S_I2S_RX_RESET; 113 | 114 | static const unsigned int conf_setup = 115 | (( 4 & I2S_BCK_DIV_NUM) << I2S_BCK_DIV_NUM_S) | // bitclock = 4.70 MHz / 3 = 1.57 MHz 116 | ((17 & I2S_CLKM_DIV_NUM) << I2S_CLKM_DIV_NUM_S) | // prescaler = 17, 80 MHz / 17 = 4.71 MHz 117 | (( 0 & I2S_BITS_MOD) << I2S_BITS_MOD_S) | // see note above, has to do with the word clock, not used here 118 | // I2S_RECE_MSB_SHIFT | // unknown 119 | // I2S_TRANS_MSB_SHIFT | // unknown 120 | // I2S_I2S_RX_START | // start the receiver 121 | // I2S_I2S_TX_START | // start the sender 122 | // I2S_MSB_RIGHT | // unknown 123 | // I2S_RIGHT_FIRST | // unknown 124 | // I2S_RECE_SLAVE_MOD | // slave (clock) receiver (?) 125 | // I2S_TRANS_SLAVE_MOD | // slave (clock) sender (?) 126 | // I2S_I2S_RX_FIFO_RESET | // reset receiver FIFO 127 | // I2S_I2S_TX_FIFO_RESET | // reset sender FIFO 128 | // I2S_I2S_RX_RESET | // reset receiver 129 | // I2S_I2S_TX_RESET | // reset sender 130 | 0; 131 | 132 | static const unsigned int fifoconf_setup = 133 | ((0 & I2S_I2S_RX_FIFO_MOD) << I2S_I2S_RX_FIFO_MOD_S) | // not used 134 | ((0 & I2S_I2S_TX_FIFO_MOD) << I2S_I2S_TX_FIFO_MOD_S) | // 0 = 16/16 bits layout 135 | // I2S_I2S_DSCR_EN | // DMA disabled FIFO mode enabled 136 | // I2S_I2S_TX_DATA_NUM I2S_I2S_TX_DATA_NUM_S | // FIXME what's this 137 | // I2S_I2S_RX_DATA_NUM I2S_I2S_RX_DATA_NUM_S | // FIXME what's this 138 | 0; 139 | 140 | static const unsigned int confchan_setup = 141 | ((0 & I2S_RX_CHAN_MOD) << I2S_RX_CHAN_MOD_S) | // dual channel (not used) 142 | ((0 & I2S_TX_CHAN_MOD) << I2S_TX_CHAN_MOD_S); // dual channel 143 | 144 | clear_peri_reg_mask(I2SCONF, conf_reset_mask); 145 | set_peri_reg_mask(I2SCONF, conf_reset_mask); 146 | clear_peri_reg_mask(I2SCONF, conf_reset_mask); 147 | 148 | espressif_opaque_start_i2s_clock(); 149 | 150 | write_peri_reg(I2SCONF, conf_setup); 151 | write_peri_reg(I2S_FIFO_CONF, fifoconf_setup); 152 | write_peri_reg(I2SCONF_CHAN, confchan_setup); 153 | 154 | clear_peri_reg_mask(SPI_SLAVE(0), all_spi_slave_ints); // I2S interrupt is shared with SPI (flash) SLAVE mode interrupts, make sure we don't get them 155 | i2s_interrupt_arm(false); 156 | ets_isr_attach(ETS_SPI_INUM, i2s_callback, (void *)0); 157 | ets_isr_unmask(1 << ETS_SPI_INUM); 158 | 159 | inited = true; 160 | 161 | return(true); 162 | } 163 | 164 | static unsigned int fifo_count = 0; 165 | 166 | bool i2s_send(unsigned int length, const uint8_t *data) 167 | { 168 | uint32_t current = 0; 169 | unsigned int idx; 170 | 171 | if(!inited) 172 | { 173 | log("! i2s: not inited\n"); 174 | return(false); 175 | } 176 | 177 | for(idx = 0; idx < length; idx++) 178 | { 179 | current <<= 8; 180 | current |= data[idx]; 181 | 182 | if((idx & 0x03) == 0x03) 183 | { 184 | write_peri_reg(I2STXFIFO, current); 185 | fifo_count++; 186 | current = 0; 187 | } 188 | } 189 | 190 | if((idx & 0x03) != 0x00) 191 | { 192 | write_peri_reg(I2STXFIFO, current); 193 | fifo_count++; 194 | } 195 | 196 | return(true); 197 | } 198 | 199 | void i2s_flush(void) 200 | { 201 | i2s_interrupt_arm(true); 202 | set_peri_reg_mask(I2SCONF, I2S_I2S_TX_START); 203 | fifo_count = 0; 204 | } 205 | -------------------------------------------------------------------------------- /font.c: -------------------------------------------------------------------------------- 1 | #include "font.h" 2 | #include "util.h" 3 | #include "sys_time.h" 4 | #include "stats.h" 5 | #include "application.h" 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | enum 13 | { 14 | font_magic_1 = 0x4afb4afb, 15 | font_magic_2 = 0x4afb4afc, 16 | font_version_0 = 0, 17 | font_version_1 = 1, 18 | font_codepoint_last_entry = 0xffffffff, 19 | fonts = 16, 20 | }; 21 | 22 | typedef struct 23 | { 24 | uint32_t magic2; 25 | uint32_t version; 26 | uint32_t width; 27 | uint32_t height; 28 | uint32_t font_bitmap[]; // start with a unicode utf8 codepoint, with bit 31 set to one, then one entry (4 bytes) per line. 29 | } font_t; 30 | 31 | typedef struct 32 | { 33 | uint32_t magic1; 34 | uint32_t version; 35 | uint32_t font[16]; // this is not a real pointer but an offset from the start of the font area 36 | } font_root_t; 37 | 38 | assert_size(font_root_t, 72); 39 | 40 | _Static_assert(offsetof(font_root_t, magic1) == 0, "offsetof(font_root_t, magic1) != 0)"); 41 | _Static_assert(offsetof(font_root_t, version) == 4, "offsetof(font_root_t, version) != 4)"); 42 | _Static_assert(offsetof(font_root_t, font[0]) == 8, "offsetof(font_root_t, font[0]) != 8)"); 43 | _Static_assert(offsetof(font_root_t, font[1]) == 12, "offsetof(font_root_t, font[1]) != 12)"); 44 | _Static_assert(offsetof(font_root_t, font[2]) == 16, "offsetof(font_root_t, font[2]) != 16)"); 45 | _Static_assert(offsetof(font_root_t, font[3]) == 20, "offsetof(font_root_t, font[3]) != 20)"); 46 | _Static_assert(offsetof(font_root_t, font[4]) == 24, "offsetof(font_root_t, font[4]) != 24)"); 47 | _Static_assert(offsetof(font_root_t, font[5]) == 28, "offsetof(font_root_t, font[5]) != 28)"); 48 | _Static_assert(offsetof(font_root_t, font[6]) == 32, "offsetof(font_root_t, font[6]) != 32)"); 49 | 50 | static bool init_done = false; 51 | static const font_t *font[fonts]; 52 | unsigned int font_logging; 53 | unsigned int font_other; 54 | unsigned int font_selected; 55 | 56 | void font_init(void) 57 | { 58 | const font_root_t *font_root = flash_cache_pointer(FONT_FLASH_OFFSET_0); 59 | 60 | if((font_root->magic1 != font_magic_1) || 61 | (font_root->version != font_version_1)) 62 | { 63 | log("font root invalid\n"); 64 | return; 65 | } 66 | 67 | for(unsigned int ix = 0; ix < fonts; ix++) 68 | { 69 | font[ix] = flash_cache_pointer(FONT_FLASH_OFFSET_0 + font_root->font[ix]); 70 | 71 | if((font[ix]->magic2 != font_magic_2) || 72 | (font[ix]->version != font_version_1)) 73 | font[ix] = (font_t *)0; 74 | } 75 | 76 | if(!config_get_uint("font.id.logging", &font_logging, -1, -1)) 77 | font_logging = 0; 78 | 79 | if(!config_get_uint("font.id.other", &font_other, -1, -1)) 80 | font_other = 0; 81 | 82 | init_done = true; 83 | } 84 | 85 | bool font_select(bool logging) 86 | { 87 | unsigned int font_new; 88 | 89 | font_new = logging ? font_logging : font_other; 90 | 91 | if(font_new > fonts) 92 | return(false); 93 | 94 | if(!font[font_new]) 95 | return(false); 96 | 97 | font_selected = font_new; 98 | 99 | return(true); 100 | } 101 | 102 | bool font_get_info(font_info_t *info) 103 | { 104 | if((font_selected >= fonts) || (!font[font_selected])) 105 | return(false); 106 | 107 | info->width = font[font_selected]->width; 108 | info->height = font[font_selected]->height; 109 | 110 | return(true); 111 | } 112 | 113 | bool font_render(unsigned int code, font_cell_t cell) 114 | { 115 | unsigned int sync_brake; 116 | unsigned int font_code; 117 | unsigned int width, height; 118 | unsigned int x, y; 119 | const uint32_t *current; 120 | uint64_t start, spent; 121 | 122 | start = time_get_us(); 123 | 124 | if((font_selected >= fonts) || (!font[font_selected])) 125 | return(false); 126 | 127 | width = font[font_selected]->width; 128 | height = font[font_selected]->height; 129 | 130 | if((width > font_cell_width) || (height > font_cell_height)) 131 | { 132 | log("font: invalid width/height\n"); 133 | return(false); 134 | } 135 | 136 | current = &font[font_selected]->font_bitmap[0]; 137 | 138 | for(;;) 139 | { 140 | for(sync_brake = 0; sync_brake < 64; sync_brake++, current++) 141 | if(*current & (1U << 31)) 142 | break; 143 | else 144 | log("skip %04x %08x\n", (unsigned int)((current - (const uint32_t *)flash_cache_pointer(FONT_FLASH_OFFSET_0)) * 4), *current); 145 | 146 | if(sync_brake >= 64) 147 | { 148 | log("font_render: sync brake\n"); 149 | return(false); 150 | } 151 | 152 | font_code = *current & ~(1U << 31); 153 | 154 | if(font_code == font_codepoint_last_entry) 155 | { 156 | log("font_render: code not found (1)\n"); 157 | return(true); 158 | } 159 | 160 | if(font_code > code) 161 | { 162 | log("font_render: code not found (2) %u %u\n", font_code, code); 163 | return(true); 164 | } 165 | 166 | if(font_code == code) 167 | break; 168 | 169 | current += height + 1; 170 | } 171 | 172 | current++; 173 | 174 | for(y = 0; y < height; y++) 175 | for(x = 0; x < width; x++) 176 | cell[y][x] = font_code == code ? (current[y] & (1 << x) ? ~0 : 0) : 0; 177 | 178 | spent = time_get_us() - start; 179 | 180 | if(spent > stat_font_render_time) 181 | stat_font_render_time = spent; 182 | 183 | return(true); 184 | } 185 | 186 | roflash const char help_description_display_font_select[] = "select display font <0-2>\n"; 187 | 188 | app_action_t application_function_display_font_select(app_params_t *parameters) 189 | { 190 | unsigned int font_logging_local, font_other_local, ix; 191 | 192 | if((parse_uint(1, parameters->src, &font_logging_local, 0, ' ') == parse_ok) && parse_uint(2, parameters->src, &font_other_local, 0, ' ') == parse_ok) 193 | { 194 | if((font_logging_local >= fonts) || (font_other_local >= fonts)) 195 | { 196 | string_format(parameters->dst, "> font must be 0 - %u\n", fonts - 1U); 197 | return(app_action_error); 198 | } 199 | 200 | if(!config_open_write()) 201 | { 202 | string_append(parameters->dst, "> cannot set config (open)\n"); 203 | return(app_action_error); 204 | } 205 | 206 | if((font_logging_local == 0) && (font_other_local == 0)) 207 | config_delete("font.id", true, -1, -1); 208 | else 209 | if(!config_set_int("font.id.logging", font_logging_local, -1, -1) || 210 | !config_set_int("font.id.other", font_other_local, -1, -1)) 211 | { 212 | config_abort_write(); 213 | string_append(parameters->dst, "> cannot set config\n"); 214 | return(app_action_error); 215 | } 216 | 217 | if(!config_close_write()) 218 | { 219 | string_append(parameters->dst, "> cannot set config (close)\n"); 220 | return(app_action_error); 221 | } 222 | 223 | font_logging = font_logging_local; 224 | font_other = font_other_local; 225 | } 226 | 227 | if(!config_get_uint("font.id.logging", &font_logging_local, -1, -1)) 228 | font_logging_local = 0; 229 | 230 | if(!config_get_uint("font.id.other", &font_other_local, -1, -1)) 231 | font_other_local = 0; 232 | 233 | for(ix = 0; ix < fonts; ix++) 234 | { 235 | string_format(parameters->dst, "> font %2u: ", ix); 236 | 237 | if(!font[ix]) 238 | string_append(parameters->dst, "unavailable"); 239 | else 240 | { 241 | string_format(parameters->dst, "%2u x %2u %-7s %-5s", 242 | font[ix]->width, font[ix]->height, 243 | ix == font_logging_local ? "logging" : "", 244 | ix == font_other_local ? "other" : ""); 245 | } 246 | 247 | string_format(parameters->dst, "\n"); 248 | } 249 | 250 | return(app_action_normal); 251 | } 252 | -------------------------------------------------------------------------------- /rboot-interface.c: -------------------------------------------------------------------------------- 1 | #include "rboot-interface.h" 2 | #include "util.h" 3 | #include "sdk.h" 4 | #include "dispatch.h" 5 | 6 | #include 7 | #include 8 | 9 | static unsigned int cache_map_entry[2] = { 0xffff, 0xffff }; 10 | 11 | typedef union 12 | { 13 | rboot_if_rtc_config_t data; 14 | uint32_t overlay[4]; 15 | } rboot_rtc_data_overlay_t; 16 | 17 | _Static_assert(sizeof(rboot_if_rtc_config_t) < sizeof(uint32_t[4]), "RTC RAM struct overlay too small"); 18 | 19 | void Cache_Read_Enable_New(void); 20 | iram attr_used void Cache_Read_Enable_New(void) 21 | { 22 | extern uint32_t SPIRead(uint32_t, void *, uint32_t); 23 | extern void Cache_Read_Enable(uint32_t, uint32_t, uint32_t); 24 | 25 | rboot_if_config_t config; 26 | const rboot_rtc_data_overlay_t *rtc_in_iospace; 27 | rboot_rtc_data_overlay_t rtc_in_dram; 28 | uint32_t cache_address; 29 | unsigned int ix; 30 | 31 | if(cache_map_entry[0] == 0xffff) 32 | { 33 | SPIRead(OFFSET_RBOOT_CFG, &config, sizeof(config)); 34 | 35 | rtc_in_iospace = (const rboot_rtc_data_overlay_t *)(0x60001100 + (rboot_if_rtc_address << 2)); 36 | 37 | for(ix = 0; ix < sizeof(rtc_in_dram.overlay) / sizeof(rtc_in_dram.overlay[0]); ix++) 38 | rtc_in_dram.overlay[ix] = rtc_in_iospace->overlay[ix]; 39 | 40 | // Don't check for next_mode == RBOOT_TEMP_ROM and neither use next_slot 41 | // because they already have been reset by rboot at this point. 42 | // Trust rboot to have selected the correct rom slot instead. 43 | 44 | if(rtc_in_dram.data.magic == rboot_if_rtc_magic) 45 | cache_address = config.slots[rtc_in_dram.data.last_slot]; 46 | else 47 | cache_address = config.slots[config.slot_current]; 48 | 49 | cache_address /= 0x100000; 50 | 51 | cache_map_entry[0] = cache_address % 2; 52 | cache_map_entry[1] = cache_address / 2; 53 | } 54 | 55 | Cache_Read_Enable(cache_map_entry[0], cache_map_entry[1], 1); 56 | } 57 | 58 | attr_const unsigned int rboot_if_mapped_slot(void) 59 | { 60 | unsigned int rv = 0; 61 | 62 | if(cache_map_entry[0]) 63 | rv |= 1 << 0; 64 | 65 | if(cache_map_entry[1]) 66 | rv |= 1 << 1; 67 | 68 | return(rv); 69 | } 70 | 71 | attr_const const char *rboot_if_boot_mode(unsigned int index) 72 | { 73 | if(index == rboot_if_conf_mode_standard) 74 | return("standard"); 75 | 76 | if(index == rboot_if_conf_mode_temp_rom) 77 | return("temp_rom"); 78 | 79 | return("unknown"); 80 | } 81 | 82 | bool rboot_if_write_config(const rboot_if_config_t *config) 83 | { 84 | bool success; 85 | string_t *buffer_string; 86 | char *buffer_cstr; 87 | unsigned int size; 88 | 89 | success = false; 90 | 91 | flash_buffer_request(fsb_rboot, true, "rboot if write config", &buffer_string, &buffer_cstr, &size); 92 | 93 | if(!buffer_string) 94 | goto exit2; 95 | 96 | if(spi_flash_read(OFFSET_RBOOT_CFG, buffer_cstr, size) != SPI_FLASH_RESULT_OK) 97 | { 98 | log("rboot_if_write_config: cannot read config sector (1)\n"); 99 | goto exit1; 100 | } 101 | 102 | if(!memory_compare(sizeof(*config), buffer_cstr, config)) 103 | { 104 | log("rboot_if_write_config: skip write\n"); 105 | success = true; 106 | goto exit1; 107 | } 108 | 109 | if(spi_flash_erase_sector(OFFSET_RBOOT_CFG / size) != SPI_FLASH_RESULT_OK) 110 | { 111 | log("rboot_if_write_config: cannot erase config sector\n"); 112 | goto exit1; 113 | } 114 | 115 | memset(buffer_cstr, 0xff, size); 116 | memcpy(buffer_cstr, config, sizeof(*config)); 117 | 118 | if(spi_flash_write(OFFSET_RBOOT_CFG, buffer_cstr, size) != SPI_FLASH_RESULT_OK) 119 | { 120 | log("rboot_if_write_config: cannot write config sector\n"); 121 | goto exit1; 122 | } 123 | 124 | memset(buffer_cstr, 0x00, size); 125 | 126 | if(spi_flash_read(OFFSET_RBOOT_CFG, buffer_cstr, size) != SPI_FLASH_RESULT_OK) 127 | { 128 | log("rboot_if_write_config: cannot read config sector (2)\n"); 129 | goto exit1; 130 | } 131 | 132 | if(memory_compare(sizeof(*config), buffer_cstr, config)) 133 | { 134 | log("rboot_if_write_config: verify failed\n"); 135 | goto exit1; 136 | } 137 | 138 | success = true; 139 | 140 | exit1: 141 | flash_buffer_release(fsb_rboot, "rboot if write config"); 142 | exit2: 143 | return(success); 144 | } 145 | 146 | bool rboot_if_read_config(rboot_if_config_t *config) 147 | { 148 | bool success; 149 | string_t *buffer_string; 150 | char *buffer_cstr; 151 | unsigned int size; 152 | 153 | success = false; 154 | 155 | flash_buffer_request(fsb_rboot, true, "rboot if read config", &buffer_string, &buffer_cstr, &size); 156 | 157 | if(!buffer_string) 158 | goto exit2; 159 | 160 | if(spi_flash_read(OFFSET_RBOOT_CFG, buffer_cstr, size) != SPI_FLASH_RESULT_OK) 161 | { 162 | log("rboot_if_read_config: cannot read config sector\n"); 163 | goto exit1; 164 | } 165 | 166 | memcpy(config, buffer_cstr, sizeof(*config)); 167 | 168 | if(config->magic != rboot_if_conf_magic) 169 | { 170 | log("rboot_if_read_config: invalid magic number\n"); 171 | goto exit1; 172 | } 173 | 174 | success = true; 175 | 176 | exit1: 177 | flash_buffer_release(fsb_rboot, "rboot if read config"); 178 | exit2: 179 | return(success); 180 | } 181 | 182 | static uint8_t checksum(const uint8_t *start, const uint8_t *end) 183 | { 184 | uint8_t cs; 185 | 186 | for(cs = rboot_if_rtc_checksum_init; start != end; start++) 187 | cs ^= *start; 188 | 189 | return(cs); 190 | } 191 | 192 | bool rboot_if_write_rtc_ram(rboot_if_rtc_config_t *config) 193 | { 194 | config->checksum = checksum((const uint8_t *)config, (const uint8_t *)&config->checksum); 195 | 196 | if(!system_rtc_mem_write(rboot_if_rtc_address, config, sizeof(*config))) 197 | return(false); 198 | 199 | return(true); 200 | } 201 | 202 | bool rboot_if_read_rtc_ram(rboot_if_rtc_config_t *config) 203 | { 204 | if(!system_rtc_mem_read(rboot_if_rtc_address, config, sizeof(*config))) 205 | return(false); 206 | 207 | if(config->magic != rboot_if_rtc_magic) 208 | return(false); 209 | 210 | return(config->checksum == checksum((const uint8_t *)config, (const uint8_t *)&config->checksum)); 211 | } 212 | 213 | void rboot_if_info(string_t *dst) 214 | { 215 | rboot_if_config_t config; 216 | rboot_if_rtc_config_t rrtc; 217 | 218 | string_format(dst, ">\n> image information:\n"); 219 | 220 | if(rboot_if_read_config(&config)) 221 | string_format(dst, 222 | "> rboot magic number: 0x%08x\n" 223 | "> rboot version: %u\n" 224 | "> boot mode: %s\n" 225 | "> current slot: %u\n" 226 | "> mapped slot: %u\n" 227 | "> slot count: %u\n" 228 | "> slot 0: 0x%06x\n" 229 | "> slot 1: 0x%06x\n", 230 | config.magic, 231 | config.version, 232 | rboot_if_boot_mode(config.boot_mode), 233 | config.slot_current, 234 | rboot_if_mapped_slot(), 235 | config.slot_count, 236 | config.slots[0], 237 | config.slots[1]); 238 | else 239 | string_format(dst, "> rboot config unavailable\n"); 240 | 241 | string_format(dst, ">\n> RTC RAM boot config information:\n"); 242 | 243 | if(rboot_if_read_rtc_ram(&rrtc)) 244 | string_format(dst, 245 | "> magic number: 0x%08x\n" 246 | "> current boot mode: %s\n" 247 | "> current slot: %u\n" 248 | "> start once boot mode: %s\n" 249 | "> start once rom slot: %u\n" 250 | "> struct checksum: %x\n", 251 | rrtc.magic, 252 | rboot_if_boot_mode(rrtc.last_mode), 253 | rrtc.last_slot, 254 | rboot_if_boot_mode(rrtc.next_mode), 255 | rrtc.temporary_slot, 256 | rrtc.checksum); 257 | else 258 | string_append(dst, "\n> rboot RTC RAM boot config unvailable\n"); 259 | } 260 | -------------------------------------------------------------------------------- /io_pcf.c: -------------------------------------------------------------------------------- 1 | #include "io_pcf.h" 2 | #include "i2c.h" 3 | #include "util.h" 4 | 5 | #include 6 | 7 | typedef struct attr_packed 8 | { 9 | uint16_t counters; 10 | uint8_t pin_output_cache; 11 | } pcf_data_instance_t; 12 | 13 | assert_size(pcf_data_instance_t, 3); 14 | 15 | typedef struct attr_packed 16 | { 17 | unsigned int polling:1; 18 | pcf_data_instance_t instance[io_pcf_instance_size]; 19 | } pcf_data_t; 20 | 21 | assert_size(pcf_data_t, (3 * io_pcf_instance_size) + 1); 22 | 23 | static pcf_data_t pcf_data; 24 | 25 | assert_size(pcf_data, (3 * io_pcf_instance_size) + 1); 26 | 27 | static io_error_t init(const struct io_info_entry_T *info) 28 | { 29 | pcf_data.instance[info->instance].counters = 0; 30 | pcf_data.instance[info->instance].pin_output_cache = 0xff; 31 | 32 | pcf_data.polling = config_flags_match(flag_pcf_no_poll) ? 0 : 1; 33 | 34 | if(i2c_send1(info->address, pcf_data.instance[info->instance].pin_output_cache) != i2c_error_ok) 35 | return(io_error); 36 | 37 | return(io_ok); 38 | } 39 | 40 | void io_pcf_pins_changed(uint32_t pin_status_mask, uint16_t pin_value_mask, uint8_t io) 41 | { 42 | io_config_pin_entry_t *pin_config; 43 | unsigned int pin; 44 | 45 | if(io >= io_id_size) 46 | { 47 | log("[pcf] pin change: invalid io\n"); 48 | return; 49 | } 50 | 51 | for(pin = 0; pin < io_pcf_pin_size; pin++) 52 | { 53 | if(!(pin_status_mask & (1 << pin))) 54 | continue; 55 | 56 | pin_config = &io_config[io][pin]; 57 | 58 | if(pin_config->llmode != io_pin_ll_counter) 59 | continue; 60 | 61 | io_pin_changed(io, pin, pin_value_mask); 62 | } 63 | } 64 | 65 | static attr_pure unsigned int max_value(const struct io_info_entry_T *info, io_data_pin_entry_t *data, const io_config_pin_entry_t *pin_config, unsigned int pin) 66 | { 67 | unsigned int value = 0; 68 | 69 | switch(pin_config->llmode) 70 | { 71 | case(io_pin_ll_input_digital): 72 | case(io_pin_ll_output_digital): 73 | { 74 | value = 0x01; 75 | break; 76 | } 77 | 78 | case(io_pin_ll_counter): 79 | { 80 | value = ~0; 81 | break; 82 | } 83 | 84 | default: 85 | break; 86 | } 87 | 88 | return(value); 89 | } 90 | 91 | static void pin_change_common_handler(const io_info_entry_t *info, bool interrupt) 92 | { 93 | static uint8_t previous_data[io_pcf_instance_size] = { 0xff, 0xff }; 94 | uint8_t current_data[io_pcf_instance_size]; 95 | uint8_t *previous, *current; 96 | uint8_t i2c_data[1]; 97 | 98 | if(!pcf_data.instance[info->instance].counters) 99 | { 100 | log("io_pcf[%u]: pin-change-common-handler: no counters\n", info->address); 101 | return; 102 | } 103 | 104 | previous = &previous_data[info->instance]; 105 | current = ¤t_data[info->instance]; 106 | 107 | if(i2c_receive(info->address, sizeof(i2c_data), i2c_data) != i2c_error_ok) 108 | return; 109 | 110 | *current = i2c_data[0] & pcf_data.instance[info->instance].counters; 111 | 112 | if(*current != *previous) 113 | dispatch_post_task(task_prio_low, task_pins_changed_pcf, *current ^ *previous, *current, info->id); 114 | else 115 | if(interrupt) 116 | log("io_pcf[%u]: pin-change-common-handler called from interrupt with no interrupt pending\n", info->address); 117 | 118 | *previous = *current; 119 | } 120 | 121 | static void periodic_slow(int io, const io_info_entry_t *info, io_data_entry_t *data, unsigned int rate_ms) 122 | { 123 | if(pcf_data.polling) 124 | pin_change_common_handler(info, false); 125 | } 126 | 127 | static void pin_change_handler(int io, io_info_entry_t *info, io_data_entry_t *data) 128 | { 129 | pin_change_common_handler(info, true); 130 | } 131 | 132 | static io_error_t pin_mode(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin) 133 | { 134 | i2c_error_t error; 135 | 136 | pcf_data.instance[info->instance].pin_output_cache &= ~(1 << pin); 137 | pcf_data.instance[info->instance].counters &= ~(1 << pin); 138 | 139 | switch(pin_config->llmode) 140 | { 141 | case(io_pin_ll_counter): 142 | { 143 | pcf_data.instance[info->instance].counters |= (1 << pin); 144 | [[fallthrough]]; 145 | } 146 | 147 | case(io_pin_ll_disabled): 148 | case(io_pin_ll_input_digital): 149 | { 150 | pcf_data.instance[info->instance].pin_output_cache |= (1 << pin); 151 | break; 152 | } 153 | 154 | case(io_pin_ll_output_digital): 155 | { 156 | break; 157 | } 158 | 159 | default: 160 | { 161 | if(error_message) 162 | string_append(error_message, "invalid mode for this pin\n"); 163 | 164 | return(io_error); 165 | } 166 | } 167 | 168 | if((error = i2c_send1(info->address, pcf_data.instance[info->instance].pin_output_cache)) != i2c_error_ok) 169 | { 170 | if(error_message) 171 | i2c_error_format_string(error_message, error); 172 | return(io_error); 173 | } 174 | 175 | return(io_ok); 176 | } 177 | 178 | static io_error_t read_pin(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin, unsigned int *value) 179 | { 180 | uint8_t i2c_data[1]; 181 | i2c_error_t error; 182 | 183 | switch(pin_config->llmode) 184 | { 185 | case(io_pin_ll_input_digital): 186 | case(io_pin_ll_output_digital): 187 | { 188 | if((error = i2c_receive(info->address, sizeof(i2c_data), i2c_data)) != i2c_error_ok) 189 | { 190 | i2c_error_format_string(error_message, error); 191 | return(io_error); 192 | } 193 | 194 | break; 195 | } 196 | 197 | default: 198 | { 199 | if(error_message) 200 | string_append(error_message, "invalid mode for this pin\n"); 201 | 202 | return(io_error); 203 | } 204 | } 205 | 206 | *value = !!(i2c_data[0] & (1 << pin)); 207 | 208 | if(pin_config->static_flags & io_flag_static_invert) 209 | *value = !*value; 210 | 211 | return(io_ok); 212 | } 213 | 214 | static io_error_t write_pin(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin, unsigned int value) 215 | { 216 | i2c_error_t error; 217 | 218 | if(pin_config->static_flags & io_flag_static_invert) 219 | value = !value; 220 | 221 | switch(pin_config->llmode) 222 | { 223 | case(io_pin_ll_output_digital): 224 | { 225 | if(value) 226 | pcf_data.instance[info->instance].pin_output_cache |= (1 << pin); 227 | else 228 | pcf_data.instance[info->instance].pin_output_cache &= ~(1 << pin); 229 | 230 | if((error = i2c_send1(info->address, pcf_data.instance[info->instance].pin_output_cache)) != i2c_error_ok) 231 | { 232 | i2c_error_format_string(error_message, error); 233 | return(io_error); 234 | } 235 | 236 | break; 237 | } 238 | 239 | default: 240 | { 241 | if(error_message) 242 | string_append(error_message, "invalid mode for this pin\n"); 243 | 244 | return(io_error); 245 | } 246 | } 247 | 248 | return(io_ok); 249 | } 250 | 251 | static io_error_t set_mask(string_t *error_message, const struct io_info_entry_T *info, unsigned int mask, unsigned int pins) 252 | { 253 | i2c_error_t error; 254 | 255 | pcf_data.instance[info->instance].pin_output_cache = pins & 0x000000ff; 256 | 257 | if((error = i2c_send1(info->address, pcf_data.instance[info->instance].pin_output_cache)) != i2c_error_ok) 258 | { 259 | i2c_error_format_string(error_message, error); 260 | return(io_error); 261 | } 262 | 263 | return(io_ok); 264 | } 265 | 266 | roflash const io_info_entry_t io_info_entry_pcf_3a = 267 | { 268 | io_id_pcf_3a, /* = 5 */ 269 | 0x3a, 270 | io_pcf_instance_3a, 271 | 8, 272 | caps_input_digital | 273 | caps_counter | 274 | caps_output_digital | 275 | caps_rotary_encoder, 276 | "PCF8574A I2C I/O expander", 277 | init, 278 | (void *)0, // postinit 279 | max_value, 280 | periodic_slow, 281 | (void *)0, // periodic_fast 282 | pin_change_handler, 283 | pin_mode, 284 | (void *)0, // get pin info 285 | read_pin, 286 | write_pin, 287 | set_mask, 288 | }; 289 | 290 | roflash const io_info_entry_t io_info_entry_pcf_26 = 291 | { 292 | io_id_pcf_26, /* = 7 */ 293 | 0x26, 294 | io_pcf_instance_26, 295 | 8, 296 | caps_input_digital | 297 | caps_counter | 298 | caps_output_digital | 299 | caps_rotary_encoder, 300 | "PCF8574 I2C I/O expander", 301 | init, 302 | (void *)0, // postinit 303 | max_value, 304 | periodic_slow, 305 | (void *)0, // periodic_fast 306 | pin_change_handler, 307 | pin_mode, 308 | (void *)0, // get pin info 309 | read_pin, 310 | write_pin, 311 | set_mask, 312 | }; 313 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | #ifndef io_h 2 | #define io_h 3 | 4 | #include "util.h" 5 | #include "config.h" 6 | #include "application.h" 7 | 8 | #include 9 | #include 10 | 11 | typedef enum 12 | { 13 | io_ok = 0, 14 | io_error, 15 | } io_error_t; 16 | 17 | assert_size(io_error_t, 4); 18 | 19 | enum 20 | { 21 | max_pins_per_io = 16, 22 | max_triggers_per_pin = 2, 23 | }; 24 | 25 | typedef enum 26 | { 27 | io_id_first = 0, 28 | io_id_gpio = 0, 29 | io_id_aux, 30 | io_id_mcp_20, 31 | io_id_mcp_21, 32 | io_id_mcp_22, 33 | io_id_pcf_3a, 34 | io_id_ledpixel, 35 | io_id_pcf_26, 36 | io_id_mcp_spi, 37 | io_id_size, 38 | } io_id_t; 39 | 40 | assert_size(io_id_t, 4); 41 | 42 | typedef struct attr_packed 43 | { 44 | unsigned int io:4; 45 | unsigned int pin:4; 46 | } config_io_t; 47 | 48 | assert_size(config_io_t, 1); 49 | 50 | typedef enum 51 | { 52 | io_dir_none, 53 | io_dir_down, 54 | io_dir_up, 55 | } io_direction_t; 56 | 57 | assert_size(io_direction_t, 4); 58 | 59 | typedef enum 60 | { 61 | io_trigger_none, 62 | io_trigger_off, 63 | io_trigger_on, 64 | io_trigger_down, 65 | io_trigger_up, 66 | io_trigger_toggle, 67 | io_trigger_stop, 68 | io_trigger_start, 69 | io_trigger_size, 70 | io_trigger_error = io_trigger_size 71 | } io_trigger_t; 72 | 73 | assert_size(io_trigger_t, 4); 74 | 75 | typedef enum 76 | { 77 | io_pin_disabled = 0, 78 | io_pin_input_digital, 79 | io_pin_counter, 80 | io_pin_output_digital, 81 | io_pin_timer, 82 | io_pin_input_analog, 83 | io_pin_output_pwm1, 84 | io_pin_i2c, 85 | io_pin_uart, 86 | io_pin_lcd, 87 | io_pin_trigger, 88 | io_pin_ledpixel, 89 | io_pin_cfa634, 90 | io_pin_output_pwm2, 91 | io_pin_rotary_encoder, 92 | io_pin_spi, 93 | io_pin_pcint, 94 | io_pin_error, 95 | io_pin_size = io_pin_error, 96 | } io_pin_mode_t; 97 | 98 | assert_size(io_pin_mode_t, 4); 99 | 100 | typedef enum 101 | { 102 | io_flag_static_none = 0 << 0, 103 | io_flag_static_autostart = 1 << 0, 104 | io_flag_static_repeat = 1 << 1, 105 | io_flag_static_pullup = 1 << 2, 106 | io_flag_static_reset_on_read = 1 << 3, 107 | io_flag_static_extended = 1 << 4, 108 | io_flag_static_grb = 1 << 5, 109 | io_flag_static_linear = 1 << 6, 110 | io_flag_static_fill8 = 1 << 7, 111 | io_flag_static_invert = 1 << 8, 112 | } io_pin_flag_static_t; 113 | 114 | assert_size(io_pin_flag_static_t, 4); 115 | 116 | typedef union 117 | { 118 | io_pin_flag_static_t io_pin_flags_static; 119 | unsigned int intvalue; 120 | } io_pin_flags_static_to_int_t; 121 | 122 | typedef enum 123 | { 124 | io_flag_dynamic_none = 0 << 0, 125 | io_flag_dynamic_suspended = 1 << 0, 126 | } io_pin_flag_dynamic_t; 127 | 128 | assert_size(io_pin_flag_dynamic_t, 4); 129 | 130 | assert_size(io_pin_flags_static_to_int_t, 4); 131 | 132 | typedef enum 133 | { 134 | io_i2c_sda, 135 | io_i2c_scl, 136 | io_i2c_error, 137 | io_i2c_size = io_i2c_error, 138 | } io_i2c_t; 139 | 140 | assert_size(io_i2c_t, 4); 141 | 142 | typedef enum 143 | { 144 | io_pin_ll_disabled = 0, 145 | io_pin_ll_input_digital, 146 | io_pin_ll_counter, 147 | io_pin_ll_output_digital, 148 | io_pin_ll_input_analog, 149 | io_pin_ll_output_pwm1, 150 | io_pin_ll_i2c, 151 | io_pin_ll_uart, 152 | io_pin_ll_output_pwm2, 153 | io_pin_ll_spi, 154 | io_pin_ll_i2s, 155 | io_pin_ll_error, 156 | io_pin_ll_size = io_pin_ll_error 157 | } io_pin_ll_mode_t; 158 | 159 | assert_size(io_pin_ll_mode_t, 4); 160 | 161 | typedef enum 162 | { 163 | io_lcd_rs = 0, 164 | io_lcd_rw, 165 | io_lcd_e, 166 | io_lcd_d0, 167 | io_lcd_d1, 168 | io_lcd_d2, 169 | io_lcd_d3, 170 | io_lcd_d4, 171 | io_lcd_d5, 172 | io_lcd_d6, 173 | io_lcd_d7, 174 | io_lcd_bl, 175 | io_lcd_error, 176 | io_lcd_size = io_lcd_error 177 | } io_lcd_mode_t; 178 | 179 | assert_size(io_lcd_mode_t, 4); 180 | 181 | typedef enum 182 | { 183 | io_renc_unset = 0, 184 | io_renc_1a, 185 | io_renc_1b, 186 | io_renc_2a, 187 | io_renc_2b, 188 | io_renc_error, 189 | io_renc_size = io_renc_error, 190 | } io_renc_pin_t; 191 | 192 | assert_size(io_renc_pin_t, 4); 193 | 194 | typedef enum 195 | { 196 | caps_input_digital = 1 << 0, 197 | caps_counter = 1 << 1, 198 | caps_output_digital = 1 << 2, 199 | caps_input_analog = 1 << 3, 200 | caps_output_pwm1 = 1 << 4, 201 | caps_output_pwm2 = 1 << 5, 202 | caps_i2c = 1 << 6, 203 | caps_ledpixel = 1 << 7, 204 | caps_uart = 1 << 8, 205 | caps_pullup = 1 << 9, 206 | caps_rotary_encoder = 1 << 10, 207 | caps_spi = 1 << 11, 208 | caps_pin_change_int = 1 << 12, 209 | } io_caps_t; 210 | 211 | assert_size(io_caps_t, 4); 212 | 213 | typedef struct attr_packed 214 | { 215 | uint32_t value; 216 | uint32_t saved_value; 217 | uint32_t speed; 218 | io_direction_t direction:2; 219 | unsigned int previous:1; 220 | } io_data_pin_entry_t; 221 | 222 | assert_size(io_data_pin_entry_t, 13); 223 | 224 | typedef struct 225 | { 226 | unsigned int detected:1; 227 | io_data_pin_entry_t pin[max_pins_per_io]; 228 | } io_data_entry_t; 229 | 230 | assert_size(io_data_entry_t, sizeof(io_data_pin_entry_t) * max_pins_per_io + 4); 231 | 232 | typedef io_data_entry_t io_data_t[io_id_size]; 233 | 234 | typedef struct attr_packed 235 | { 236 | io_pin_mode_t mode:5; 237 | io_pin_ll_mode_t llmode:4; 238 | io_pin_flag_static_t static_flags:10; 239 | io_pin_flag_dynamic_t dynamic_flags:1; 240 | io_direction_t direction:2; 241 | unsigned int speed:18; 242 | 243 | union 244 | { 245 | struct attr_packed 246 | { 247 | unsigned int lower_bound:20; 248 | unsigned int upper_bound:20; 249 | } output_pwm; 250 | 251 | struct attr_packed 252 | { 253 | io_i2c_t pin_mode; 254 | } i2c; 255 | 256 | struct attr_packed 257 | { 258 | io_lcd_mode_t pin_use; 259 | } lcd; 260 | 261 | struct attr_packed 262 | { 263 | io_renc_pin_t pin_type:8; 264 | unsigned int partner:8; 265 | struct attr_packed 266 | { 267 | int remote:8; 268 | int io:8; 269 | int pin:8; 270 | } trigger_pin; 271 | } renc; 272 | 273 | struct attr_packed 274 | { 275 | config_io_t io; 276 | io_trigger_t action:8; 277 | } trigger[max_triggers_per_pin]; 278 | } shared; 279 | } io_config_pin_entry_t; 280 | 281 | assert_size(io_config_pin_entry_t, 10); 282 | 283 | typedef const struct io_info_entry_T 284 | { 285 | attr_flash_align io_id_t id; 286 | attr_flash_align uint32_t address; 287 | attr_flash_align uint32_t instance; 288 | attr_flash_align uint32_t pins; 289 | attr_flash_align io_caps_t caps; 290 | attr_flash_align const char *name; 291 | attr_flash_align io_error_t (* const init_fn) ( const struct io_info_entry_T *); 292 | attr_flash_align void (* const post_init_fn) ( const struct io_info_entry_T *); 293 | attr_flash_align unsigned int(* const pin_max_value_fn) ( const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, unsigned int pin); 294 | attr_flash_align void (* const periodic_slow_fn) (int io, const struct io_info_entry_T *, io_data_entry_t *, unsigned int period); 295 | attr_flash_align void (* const periodic_fast_fn) (int io, const struct io_info_entry_T *, io_data_entry_t *, unsigned int period); 296 | attr_flash_align void (* const pin_change_int_fn) (int io, const struct io_info_entry_T *, io_data_entry_t *); 297 | attr_flash_align io_error_t (* const init_pin_mode_fn) (string_t *error, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int); 298 | attr_flash_align io_error_t (* const get_pin_info_fn) (string_t *error, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int); 299 | attr_flash_align io_error_t (* const read_pin_fn) (string_t *error, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int, unsigned int *); 300 | attr_flash_align io_error_t (* const write_pin_fn) (string_t *error, const struct io_info_entry_T *, io_data_pin_entry_t *, const io_config_pin_entry_t *, int, unsigned int); 301 | attr_flash_align io_error_t (* const set_mask_fn) (string_t *error, const struct io_info_entry_T *, unsigned int mask, unsigned int pins); 302 | } io_info_entry_t; 303 | 304 | assert_size(io_info_entry_t, 68); 305 | 306 | extern io_config_pin_entry_t io_config[io_id_size][max_pins_per_io]; 307 | 308 | void io_init(void); 309 | void io_pin_changed(unsigned int io, unsigned int pin, uint32_t pin_value_mask); 310 | void io_periodic_slow(unsigned int period); 311 | void io_periodic_fast(unsigned int period); 312 | unsigned int io_pin_max_value(unsigned int io, unsigned int pin); 313 | io_error_t io_read_pin(string_t *, unsigned int, unsigned int, unsigned int *); 314 | io_error_t io_write_pin(string_t *, unsigned int, unsigned int, unsigned int); 315 | io_error_t io_set_mask(string_t *error, int io, unsigned int mask, unsigned int pins); 316 | io_error_t io_trigger_pin(string_t *, unsigned int, unsigned int, io_trigger_t); 317 | io_error_t io_traits(string_t *, unsigned int io, unsigned int pin, io_pin_mode_t *mode, unsigned int *lower_bound, unsigned int *upper_bound, int *step, unsigned int *value); 318 | void io_config_dump(string_t *dst, int io_id, int pin_id, bool html); 319 | void io_string_from_ll_mode(string_t *, io_pin_ll_mode_t, int pad); 320 | 321 | app_action_t application_function_io_mode(app_params_t *); 322 | app_action_t application_function_io_read(app_params_t *); 323 | app_action_t application_function_io_write(app_params_t *); 324 | app_action_t application_function_io_trigger(app_params_t *); 325 | app_action_t application_function_io_set_flag(app_params_t *); 326 | app_action_t application_function_io_clear_flag(app_params_t *); 327 | app_action_t application_function_io_set_mask(app_params_t *); 328 | app_action_t application_function_io_suspend(app_params_t *); 329 | app_action_t application_function_io_resume(app_params_t *); 330 | 331 | #endif 332 | -------------------------------------------------------------------------------- /io_ledpixel.c: -------------------------------------------------------------------------------- 1 | #include "io_ledpixel.h" 2 | #include "util.h" 3 | #include "uart.h" 4 | #include "i2s.h" 5 | #include "io_gpio.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef struct attr_packed 13 | { 14 | unsigned int enabled:1; 15 | unsigned int extended:1; 16 | unsigned int grb:1; 17 | unsigned int fill8:1; 18 | unsigned int value:32; 19 | } ledpixel_data_pin_t; 20 | 21 | assert_size(ledpixel_data_pin_t, 5); 22 | 23 | typedef union attr_packed 24 | { 25 | struct 26 | { 27 | unsigned int b:5; 28 | unsigned int g:5; 29 | unsigned int r:5; 30 | unsigned int flag:1; 31 | unsigned int pinmask:16; 32 | }; 33 | unsigned int value; 34 | } ledpixel_mask_value_t; 35 | 36 | assert_size(ledpixel_mask_value_t, 4); 37 | 38 | roflash static const unsigned int lut_5_8[32] = 39 | { 40 | 0, // 0 0x00 41 | 1, // 1 0x01 42 | 2, // 2 0x02 43 | 3, // 3 0x03 44 | 4, // 4 0x04 45 | 5, // 5 0x05 46 | 6, // 6 0x06 47 | 7, // 7 0x07 48 | 8, // 8 0x08 49 | 10, // 9 0x0a 50 | 12, // 10 0x0c 51 | 15, // 11 0x0f 52 | 18, // 12 0x12 53 | 21, // 13 0x15 54 | 25, // 14 0x19 55 | 28, // 15 0x1c 56 | 32, // 16 0x20 57 | 40, // 17 0x28 58 | 48, // 18 0x30 59 | 56, // 19 0x38 60 | 64, // 20 0x40 61 | 72, // 21 0x48 62 | 80, // 22 0x50 63 | 88, // 23 0x58 64 | 96, // 24 0x60 65 | 112, // 25 0x70 66 | 128, // 26 0x80 67 | 144, // 27 0x90 68 | 160, // 28 0xa0 69 | 192, // 29 0xc0 70 | 224, // 30 0xe0 71 | 255, // 31 0xff 72 | }; 73 | 74 | static bool use_uart_0 = false; 75 | static bool use_uart_1 = false; 76 | static bool use_i2s = false; 77 | static bool use_i2s_invert = false; 78 | 79 | static ledpixel_data_pin_t ledpixel_data_pin[max_pins_per_io]; 80 | 81 | static unsigned int lookup_5_to_8(unsigned int entry) 82 | { 83 | if(entry >= sizeof(lut_5_8)) 84 | return(0xff); 85 | 86 | return(lut_5_8[entry]); 87 | } 88 | 89 | static void value_mask_to_rgb(unsigned int value, unsigned int *pinmask, unsigned int *flag, unsigned int *rgb) 90 | { 91 | ledpixel_mask_value_t mask_value; 92 | unsigned int r, g, b; 93 | 94 | mask_value.value = value; 95 | 96 | *pinmask = mask_value.pinmask; 97 | *flag = mask_value.flag; 98 | 99 | r = lookup_5_to_8(mask_value.r); 100 | g = lookup_5_to_8(mask_value.g); 101 | b = lookup_5_to_8(mask_value.b); 102 | 103 | *rgb = (r << 16) | (g << 8) | (b << 0); 104 | } 105 | 106 | static void send_byte_uart(unsigned int byte) 107 | { 108 | // from an idea by nodemcu coders: https://github.com/nodemcu/nodemcu-firmware/blob/master/app/modules/ws2812.c 109 | 110 | static const unsigned int bit_pattern[4] = 111 | { // mirror add start/stop negate 112 | 0b110111, // 00 111-011 [0]111-011[1] 1000-1000 113 | 0b000111, // 01 111-000 [0]111-000[1] 1000-1110 114 | 0b110100, // 10 001-011 [0]001-011[1] 1110-1000 115 | 0b000100, // 11 001-000 [0]001-000[1] 1110-1110 116 | }; 117 | 118 | unsigned int byte_bit_index; 119 | unsigned int by_six = 0; 120 | 121 | for(byte_bit_index = 0; byte_bit_index < 4; byte_bit_index++) 122 | { 123 | by_six = bit_pattern[(byte & 0b11000000) >> 6]; 124 | byte <<= 2; 125 | 126 | if(use_uart_0) 127 | uart_send(0, by_six); 128 | 129 | if(use_uart_1) 130 | uart_send(1, by_six); 131 | } 132 | } 133 | 134 | static void send_byte_i2s(unsigned int byte_value_in) 135 | { 136 | static const unsigned int off_pattern_normal = 0b1000; 137 | static const unsigned int on_pattern_normal = 0b1110; 138 | static const unsigned int off_pattern_invert = 0b0111; 139 | static const unsigned int on_pattern_invert = 0b0001; 140 | uint8_t buffer[4]; 141 | unsigned int bit_in; 142 | unsigned int byte_out; 143 | unsigned int pattern; 144 | 145 | for(bit_in = 0, byte_out = 0; (bit_in < 8) && (byte_out < 4); bit_in++) 146 | { 147 | pattern = (byte_value_in & (1 << (7 - bit_in))) ? (use_i2s_invert ? on_pattern_invert : on_pattern_normal) : (use_i2s_invert ? off_pattern_invert : off_pattern_normal); 148 | 149 | if(bit_in & 0x01) // after every second input bit the output nibble is full 150 | { 151 | buffer[byte_out] <<= 4; 152 | buffer[byte_out] |= pattern; 153 | byte_out++; 154 | } 155 | else 156 | buffer[byte_out] = pattern; 157 | } 158 | 159 | // always send at least four bytes at once, 160 | // to prevent padding zero bytes from being 161 | i2s_send(sizeof(buffer), buffer); // inserted as i2s uses a fifo of 32 bit words 162 | } 163 | 164 | static void send_byte(unsigned int byte) 165 | { 166 | if(use_i2s) 167 | send_byte_i2s(byte); 168 | 169 | if(use_uart_0 || use_uart_1) 170 | send_byte_uart(byte); 171 | } 172 | 173 | static void send_all(bool force) 174 | { 175 | static const uint8_t zero_sample_normal[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 176 | static const uint8_t zero_sample_invert[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 177 | unsigned int pin, fill; 178 | 179 | for(pin = 0; pin < max_pins_per_io; pin++) 180 | { 181 | if(!force && !ledpixel_data_pin[pin].enabled) 182 | break; 183 | 184 | for(fill = ledpixel_data_pin[pin].fill8 ? 8 : 1; fill > 0; fill--) 185 | { 186 | if(ledpixel_data_pin[pin].grb) 187 | { 188 | send_byte((ledpixel_data_pin[pin].value & 0x0000ff00) >> 8); 189 | send_byte((ledpixel_data_pin[pin].value & 0x00ff0000) >> 16); 190 | } 191 | else 192 | { 193 | send_byte((ledpixel_data_pin[pin].value & 0x00ff0000) >> 16); 194 | send_byte((ledpixel_data_pin[pin].value & 0x0000ff00) >> 8); 195 | } 196 | 197 | send_byte((ledpixel_data_pin[pin].value & 0x000000ff) >> 0); 198 | 199 | // some ws2812's have four leds (including a white one) and need an extra byte to be sent for it 200 | 201 | if(ledpixel_data_pin[pin].extended) 202 | send_byte((ledpixel_data_pin[pin].value & 0xff000000) >> 24); 203 | } 204 | 205 | if(use_uart_0) 206 | uart_flush(0); 207 | 208 | if(use_uart_1) 209 | uart_flush(1); 210 | } 211 | 212 | if(use_i2s) 213 | { 214 | if(use_i2s_invert) 215 | i2s_send(sizeof(zero_sample_invert), zero_sample_invert); // the last "sample" (4 bytes) get repeated until the transmitter is stopped 216 | else 217 | i2s_send(sizeof(zero_sample_normal), zero_sample_normal); // the last "sample" (4 bytes) get repeated until the transmitter is stopped 218 | 219 | i2s_flush(); 220 | } 221 | } 222 | 223 | io_ledpixel_mode_t io_ledpixel_mode(unsigned int io, unsigned int pin) 224 | { 225 | unsigned int uart; 226 | 227 | if(io != io_id_gpio) 228 | return(ledpixel_invalid); 229 | 230 | if(io_gpio_get_i2s_from_pin(pin) == gpio_i2s_pin_output_data) 231 | return(ledpixel_i2s); 232 | 233 | uart = io_gpio_get_uart_from_pin(pin); 234 | 235 | if(uart == 0) 236 | return(ledpixel_uart_0); 237 | 238 | if(uart == 1) 239 | return(ledpixel_uart_1); 240 | 241 | return(ledpixel_invalid); 242 | } 243 | 244 | bool io_ledpixel_pre_init(unsigned int io, unsigned int pin) 245 | { 246 | io_config_pin_entry_t *pin_config; 247 | 248 | switch(io_ledpixel_mode(io, pin)) 249 | { 250 | case(ledpixel_i2s): 251 | { 252 | use_i2s = true; 253 | pin_config = &io_config[io][pin]; 254 | 255 | if(pin_config->static_flags & io_flag_static_invert) 256 | use_i2s_invert = true; 257 | 258 | break; 259 | } 260 | 261 | case(ledpixel_uart_0): 262 | { 263 | use_uart_0 = true; 264 | break; 265 | } 266 | 267 | case(ledpixel_uart_1): 268 | { 269 | use_uart_1 = true; 270 | break; 271 | } 272 | 273 | default: 274 | { 275 | return(false); 276 | } 277 | } 278 | 279 | return(true); 280 | } 281 | 282 | static io_error_t init(const struct io_info_entry_T *info) 283 | { 284 | if(!use_uart_0 && !use_uart_1 && !use_i2s) 285 | return(io_error); 286 | 287 | if(use_uart_0) 288 | { 289 | uart_baudrate(0, 3200000); 290 | uart_data_bits(0, 6); 291 | uart_stop_bits(0, 1); 292 | uart_parity(0, parity_none); 293 | } 294 | 295 | if(use_uart_1) 296 | { 297 | uart_baudrate(1, 3200000); 298 | uart_data_bits(1, 6); 299 | uart_stop_bits(1, 1); 300 | uart_parity(1, parity_none); 301 | } 302 | 303 | if(use_i2s && !i2s_init()) 304 | return(io_error); 305 | 306 | return(io_ok); 307 | } 308 | 309 | static void post_init(const struct io_info_entry_T *info) 310 | { 311 | send_all(true); 312 | } 313 | 314 | static attr_pure unsigned int pin_max_value(const struct io_info_entry_T *info, io_data_pin_entry_t *data, const io_config_pin_entry_t *pin_config, unsigned int pin) 315 | { 316 | unsigned int value = 0; 317 | 318 | if(pin_config->llmode == io_pin_ll_output_pwm1) 319 | value = ledpixel_data_pin[pin].extended ? 0xffffffff : 0x00ffffff; 320 | 321 | return(value); 322 | } 323 | 324 | static io_error_t init_pin_mode(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin) 325 | { 326 | ledpixel_data_pin[pin].enabled = pin_config->llmode == io_pin_ll_output_pwm1; 327 | ledpixel_data_pin[pin].extended = !!(pin_config->static_flags & io_flag_static_extended); 328 | ledpixel_data_pin[pin].grb = !!(pin_config->static_flags & io_flag_static_grb); 329 | ledpixel_data_pin[pin].fill8 = !!(pin_config->static_flags & io_flag_static_fill8); 330 | ledpixel_data_pin[pin].value = 0; 331 | 332 | return(io_ok); 333 | } 334 | 335 | static io_error_t read_pin(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin, unsigned int *value) 336 | { 337 | *value = ledpixel_data_pin[pin].value; 338 | 339 | return(io_ok); 340 | } 341 | 342 | static io_error_t write_pin(string_t *error_message, const struct io_info_entry_T *info, io_data_pin_entry_t *pin_data, const io_config_pin_entry_t *pin_config, int pin, unsigned int value) 343 | { 344 | ledpixel_data_pin[pin].value = value; 345 | 346 | send_all(false); 347 | 348 | return(io_ok); 349 | } 350 | 351 | io_error_t io_ledpixel_pinmask(unsigned int mask) 352 | { 353 | unsigned int pin; 354 | unsigned int pinmask, flag, rgb; 355 | 356 | if(!use_uart_0 && !use_uart_1 && !use_i2s) 357 | return(io_error); 358 | 359 | value_mask_to_rgb(mask, &pinmask, &flag, &rgb); 360 | 361 | for(pin = 0; pin < max_pins_per_io; pin++) 362 | { 363 | if(!ledpixel_data_pin[pin].enabled) 364 | break; 365 | 366 | if(pinmask & (1 << pin)) 367 | ledpixel_data_pin[pin].value = rgb; 368 | } 369 | 370 | send_all(false); 371 | 372 | return(io_ok); 373 | } 374 | 375 | roflash const io_info_entry_t io_info_entry_ledpixel = 376 | { 377 | io_id_ledpixel, /* = 6 */ 378 | 0x00, 379 | 0, 380 | 16, 381 | caps_output_pwm1, 382 | "led string", 383 | init, 384 | post_init, 385 | pin_max_value, 386 | (void *)0, // periodic slow 387 | (void *)0, // periodic fast 388 | (void *)0, // pin change handler 389 | init_pin_mode, 390 | (void *)0, // get pin info 391 | read_pin, 392 | write_pin, 393 | (void *)0, // set_mask // FIXME this can be implemented, but may not be very useful 394 | }; 395 | -------------------------------------------------------------------------------- /sequencer.c: -------------------------------------------------------------------------------- 1 | #include "sequencer.h" 2 | #include "sys_time.h" 3 | #include "io.h" 4 | #include "dispatch.h" 5 | 6 | #include 7 | #include 8 | 9 | typedef struct 10 | { 11 | bool flash_valid; 12 | int start; 13 | int current; 14 | uint64_t current_end_time; 15 | int repeats; 16 | } sequencer_t; 17 | 18 | static sequencer_t sequencer; 19 | 20 | typedef struct 21 | { 22 | union 23 | { 24 | struct 25 | { 26 | unsigned int active:1; 27 | unsigned int io:4; 28 | unsigned int pin:4; 29 | unsigned int duration:23; 30 | unsigned int value:32; 31 | }; 32 | struct 33 | { 34 | unsigned int magic:32; 35 | unsigned int version:32; 36 | }; 37 | struct 38 | { 39 | uint32_t word[2]; 40 | }; 41 | }; 42 | } sequencer_entry_t; 43 | 44 | assert_size(sequencer_entry_t, 8); 45 | 46 | enum 47 | { 48 | sequencer_flash_magic = 0x4afc4afb, 49 | sequencer_flash_version = 0, 50 | sequencer_flash_sectors = 4, 51 | sequencer_flash_size = sequencer_flash_sectors * SPI_FLASH_SEC_SIZE, // 4 sectors of 4k bytes each 52 | sequencer_flash_entries = sequencer_flash_size / sizeof(sequencer_entry_t), 53 | sequencer_flash_entries_per_sector = sequencer_flash_entries / sequencer_flash_sectors, 54 | sequencer_flash_memory_map_start = 0x40200000, 55 | }; 56 | 57 | _Static_assert(sequencer_flash_entries == 2048, "flash sequencer size incorrect"); 58 | _Static_assert(sequencer_flash_entries_per_sector == 512, "flash sequencer per sector size incorrect"); 59 | 60 | static bool clear_all_flash_entries(unsigned int mirror) 61 | { 62 | bool success; 63 | sequencer_entry_t *entry; 64 | unsigned int offset, sector, current = 0; 65 | string_t *buffer_string; 66 | char *buffer_cstr; 67 | unsigned int size; 68 | 69 | success = false; 70 | 71 | if(mirror > 1) 72 | goto error2; 73 | 74 | if(mirror == 0) 75 | offset = SEQUENCER_FLASH_OFFSET_0; 76 | else 77 | offset = SEQUENCER_FLASH_OFFSET_1; 78 | 79 | if(offset == 0) // plain image, no mirror offset 80 | { 81 | success = true; 82 | goto error2; 83 | } 84 | 85 | flash_buffer_request(fsb_sequencer, true, "sequencer clear all flash entries", &buffer_string, &buffer_cstr, &size); 86 | 87 | if(!buffer_string) 88 | goto error2; 89 | 90 | for(sector = 0; sector < sequencer_flash_sectors; sector++) 91 | { 92 | entry = (sequencer_entry_t *)(void *)buffer_cstr; 93 | 94 | if(sector == 0) 95 | { 96 | entry->magic = sequencer_flash_magic; 97 | entry->version = sequencer_flash_version; 98 | entry++; 99 | } 100 | 101 | for(; ((char *)entry - buffer_cstr) < (int)size; entry++) 102 | { 103 | 104 | entry->active = 0; 105 | entry->io = 0; 106 | entry->pin = 0; 107 | entry->duration = 0; 108 | entry->value = current++; 109 | } 110 | 111 | log("sequencer clear: offset: %x, sector %u, entries written to flash: %u, entryp = %d\n", 112 | offset + (sector * SPI_FLASH_SEC_SIZE), 113 | sector, 114 | current, 115 | (char *)entry - buffer_cstr); 116 | 117 | if(spi_flash_erase_sector((offset + (sector * size)) / size) != SPI_FLASH_RESULT_OK) 118 | goto error1; 119 | 120 | if(spi_flash_write(offset + (sector * size), buffer_cstr, size) != SPI_FLASH_RESULT_OK) 121 | goto error1; 122 | } 123 | 124 | success = true; 125 | 126 | error1: 127 | flash_buffer_release(fsb_sequencer, "sequencer clear all flash entries"); 128 | error2: 129 | return(success); 130 | } 131 | 132 | static bool get_flash_entry(unsigned int index, sequencer_entry_t *entry) 133 | { 134 | const sequencer_entry_t *entries_in_flash; 135 | 136 | if(index >= sequencer_flash_entries) 137 | return(false); 138 | 139 | // note: this will always use either mirror 0 or mirror 1 depending on which image/slot is loaded, due to the flash mapping window 140 | entries_in_flash = (const sequencer_entry_t *)(sequencer_flash_memory_map_start + SEQUENCER_FLASH_OFFSET_0); 141 | 142 | // careful to only read complete 32 bits words from mapped flash 143 | entry->word[0] = entries_in_flash[index].word[0]; 144 | entry->word[1] = entries_in_flash[index].word[1]; 145 | 146 | return(true); 147 | } 148 | 149 | static bool update_flash_entry(unsigned int index, unsigned int mirror, const sequencer_entry_t *entry) 150 | { 151 | bool success; 152 | sequencer_entry_t *entries_in_buffer, *entry_in_buffer; 153 | unsigned int flash_start_offset, sector; 154 | string_t *buffer_string; 155 | char *buffer_cstr; 156 | unsigned int size; 157 | 158 | success = false; 159 | 160 | if(!sequencer.flash_valid) 161 | goto error2; 162 | 163 | if(index >= sequencer_flash_entries) 164 | goto error2; 165 | 166 | if(mirror > 1) 167 | goto error2; 168 | 169 | flash_buffer_request(fsb_sequencer, true, "sequencer update flash entry", &buffer_string, &buffer_cstr, &size); 170 | 171 | if(!buffer_string) 172 | goto error2; 173 | 174 | if(mirror == 0) 175 | flash_start_offset = SEQUENCER_FLASH_OFFSET_0; 176 | else 177 | flash_start_offset = SEQUENCER_FLASH_OFFSET_1; 178 | 179 | if(flash_start_offset == 0) // plain image, no mirror offset 180 | { 181 | success = true; 182 | goto error1; 183 | } 184 | 185 | sector = (index * sizeof(sequencer_entry_t)) / size; 186 | 187 | //log("update flash entry: update entry: %u, sector: %u, offset index: %u, flash start offset: %x\n", 188 | //index, 189 | //sector, 190 | //index - (sector * sequencer_flash_entries_per_sector), 191 | //flash_start_offset); 192 | 193 | if(spi_flash_read(flash_start_offset + (sector * size), buffer_cstr, size) != SPI_FLASH_RESULT_OK) 194 | goto error1; 195 | 196 | entries_in_buffer = (sequencer_entry_t *)(void *)buffer_cstr; 197 | entry_in_buffer = &entries_in_buffer[index - (sector * sequencer_flash_entries_per_sector)]; 198 | 199 | //log("* buffer offset: %d\n", (char *)&entries_in_buffer[index - (sector * sequencer_flash_entries_per_sector)] - buffer); 200 | //log("* entry1: io: %d, pin: %d, duration: %d, value: %u\n", entry_in_buffer->io, entry_in_buffer->pin, entry_in_buffer->duration, entry_in_buffer->value); 201 | 202 | *entry_in_buffer = *entry; 203 | 204 | //log("* entry2: io: %d, pin: %d, duration: %d, value: %u\n", entry_in_buffer->io, entry_in_buffer->pin, entry_in_buffer->duration, entry_in_buffer->value); 205 | 206 | if(spi_flash_erase_sector((flash_start_offset + (sector * size)) / size) != SPI_FLASH_RESULT_OK) 207 | goto error1; 208 | 209 | if(spi_flash_write(flash_start_offset + (sector * size), buffer_cstr, size) != SPI_FLASH_RESULT_OK) 210 | goto error1; 211 | 212 | success = true; 213 | 214 | error1: 215 | flash_buffer_release(fsb_sequencer, "sequencer update flash entry"); 216 | error2: 217 | return(success); 218 | } 219 | 220 | attr_pure int sequencer_get_start(void) 221 | { 222 | return(sequencer.start); 223 | } 224 | 225 | attr_pure int sequencer_get_current(void) 226 | { 227 | return(sequencer.current); 228 | } 229 | 230 | iram attr_pure uint64_t sequencer_get_current_end_time(void) 231 | { 232 | return(sequencer.current_end_time); 233 | } 234 | 235 | iram attr_pure int sequencer_get_repeats(void) 236 | { 237 | return(sequencer.repeats); 238 | } 239 | 240 | void sequencer_get_status(bool *running, unsigned int *start, unsigned int *flash_size, unsigned int *flash_size_entries, 241 | unsigned int *flash_offset_flash0, unsigned int *flash_offset_flash1, unsigned int *flash_offset_mapped) 242 | { 243 | *running = sequencer.repeats > 0; 244 | *start = sequencer.start; 245 | *flash_size = sequencer_flash_sectors * SPI_FLASH_SEC_SIZE; 246 | *flash_size_entries = sequencer_flash_entries; 247 | *flash_offset_flash0 = SEQUENCER_FLASH_OFFSET_0; 248 | *flash_offset_flash1 = SEQUENCER_FLASH_OFFSET_1; 249 | *flash_offset_mapped = sequencer_flash_memory_map_start + SEQUENCER_FLASH_OFFSET_0; 250 | } 251 | 252 | bool sequencer_clear(void) 253 | { 254 | if(!clear_all_flash_entries(0)) 255 | return(false); 256 | if(!clear_all_flash_entries(1)) 257 | return(false); 258 | 259 | sequencer_init(); 260 | 261 | return(sequencer.flash_valid); 262 | } 263 | 264 | bool sequencer_get_entry(unsigned int index, bool *active, int *io, int *pin, unsigned int *value, unsigned int *duration) 265 | { 266 | sequencer_entry_t entry; 267 | 268 | if(!sequencer.flash_valid) 269 | return(false); 270 | 271 | index++; // index = 0 is header 272 | 273 | if(index >= sequencer_flash_entries) 274 | return(false); 275 | 276 | if(!get_flash_entry(index, &entry)) 277 | return(false); 278 | 279 | if(active) 280 | *active = entry.active; 281 | 282 | if(io) 283 | *io = entry.io; 284 | 285 | if(pin) 286 | *pin = entry.pin; 287 | 288 | if(duration) 289 | *duration = entry.duration; 290 | 291 | if(value) 292 | *value = entry.value; 293 | 294 | return(true); 295 | } 296 | 297 | bool sequencer_set_entry(unsigned int index, int io, int pin, uint32_t value, int duration) 298 | { 299 | sequencer_entry_t entry; 300 | 301 | if(!sequencer.flash_valid) 302 | return(false); 303 | 304 | index++; 305 | 306 | if(index >= sequencer_flash_entries) 307 | return(false); 308 | 309 | entry.active = 1; 310 | entry.io = io; 311 | entry.pin = pin; 312 | entry.duration = duration; 313 | entry.value = value; 314 | 315 | if(!update_flash_entry(index, 0, &entry)) 316 | return(false); 317 | 318 | return(update_flash_entry(index, 1, &entry)); 319 | } 320 | 321 | bool sequencer_remove_entry(unsigned int index) 322 | { 323 | sequencer_entry_t entry; 324 | 325 | if(!sequencer.flash_valid) 326 | return(false); 327 | 328 | index++; 329 | 330 | if(index >= sequencer_flash_entries) 331 | return(false); 332 | 333 | entry.active = 0; 334 | entry.io = 0; 335 | entry.pin = 0; 336 | entry.duration = 0; 337 | entry.value = 0; 338 | 339 | if(!update_flash_entry(index, 0, &entry)) 340 | return(false); 341 | 342 | return(update_flash_entry(index, 1, &entry)); 343 | } 344 | 345 | void sequencer_init(void) 346 | { 347 | sequencer_entry_t header; 348 | 349 | sequencer_stop(); 350 | 351 | sequencer.flash_valid = 0; 352 | 353 | if(get_flash_entry(0, &header) && (header.magic == sequencer_flash_magic) && (header.version == sequencer_flash_version)) 354 | sequencer.flash_valid = 1; 355 | } 356 | 357 | void sequencer_start(unsigned int start, unsigned int repeats) 358 | { 359 | sequencer.start = start; 360 | sequencer.current = sequencer.start - 1; 361 | sequencer.current_end_time = 0; 362 | sequencer.repeats = repeats; 363 | } 364 | 365 | void sequencer_stop(void) 366 | { 367 | sequencer.start = 0; 368 | sequencer.current = -1; 369 | sequencer.current_end_time = 0; 370 | sequencer.repeats = 0; 371 | } 372 | 373 | void sequencer_run(void) 374 | { 375 | int io, pin; 376 | unsigned int value, duration; 377 | bool active; 378 | 379 | sequencer.current++; 380 | 381 | if(!sequencer_get_entry(sequencer.current, &active, &io, &pin, &value, &duration) || !active) 382 | { 383 | if(--sequencer.repeats <= 0) 384 | { 385 | sequencer_stop(); 386 | return; 387 | } 388 | 389 | sequencer.current = sequencer.start; 390 | 391 | if(!sequencer_get_entry(sequencer.current, &active, &io, &pin, &value, &duration) || !active) 392 | { 393 | sequencer_stop(); 394 | return; 395 | } 396 | } 397 | 398 | sequencer.current_end_time = (time_get_us() / 1000) + duration; 399 | 400 | io_write_pin((string_t *)0, io, pin, value); 401 | } 402 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/netio.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * MetIO Server 4 | * 5 | */ 6 | 7 | /* 8 | * Redistribution and use in source and binary forms, with or without modification, 9 | * are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 3. The name of the author may not be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 28 | * OF SUCH DAMAGE. 29 | * 30 | * This file is part of the lwIP TCP/IP stack. 31 | * 32 | */ 33 | #include "lwip/opt.h" 34 | 35 | #if LWIP_TCP 36 | #include "lwip/tcp.h" 37 | 38 | #ifdef MEMLEAK_DEBUG 39 | static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; 40 | #endif 41 | 42 | /* 43 | * This implements a netio server. 44 | * The client sends a command word (4 bytes) then a data length word (4 bytes). 45 | * If the command is "receive", the server is to consume "data length" bytes into 46 | * a circular buffer until the first byte is non-zero, then it is to consume 47 | * another command/data pair. 48 | * If the command is "send", the server is to send "data length" bytes from a circular 49 | * buffer with the first byte being zero, until "some time" (6 seconds in the 50 | * current netio126.zip download) has passed and then send one final buffer with 51 | * the first byte being non-zero. Then it is to consume another command/data pair. 52 | */ 53 | 54 | /* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ 55 | 56 | /* implementation options */ 57 | #define NETIO_BUF_SIZE (4 * 1024) 58 | #define NETIO_USE_STATIC_BUF 0 59 | 60 | /* NetIO server state definition */ 61 | #define NETIO_STATE_WAIT_FOR_CMD 0 62 | #define NETIO_STATE_RECV_DATA 1 63 | #define NETIO_STATE_SEND_DATA 2 64 | #define NETIO_STATE_SEND_DATA_LAST 3 65 | #define NETIO_STATE_DONE 4 66 | 67 | struct netio_state { 68 | u32_t state; 69 | u32_t cmd; 70 | u32_t data_len; 71 | u32_t cntr; 72 | u8_t * buf_ptr; 73 | u32_t buf_pos; 74 | u32_t first_byte; 75 | u32_t time_stamp; 76 | }; 77 | 78 | /* NetIO command protocol definition */ 79 | #define NETIO_CMD_QUIT 0 80 | #define NETIO_CMD_C2S 1 81 | #define NETIO_CMD_S2C 2 82 | #define NETIO_CMD_RES 3 83 | 84 | static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); 85 | 86 | static void ICACHE_FLASH_ATTR 87 | netio_close(void *arg, struct tcp_pcb *pcb) 88 | { 89 | err_t err; 90 | 91 | struct netio_state *ns = arg; 92 | ns->state = NETIO_STATE_DONE; 93 | tcp_recv(pcb, NULL); 94 | err = tcp_close(pcb); 95 | 96 | if (err != ERR_OK) { 97 | /* closing failed, try again later */ 98 | tcp_recv(pcb, netio_recv); 99 | } else { 100 | /* closing succeeded */ 101 | #if NETIO_USE_STATIC_BUF != 1 102 | if(ns->buf_ptr != NULL){ 103 | mem_free(ns->buf_ptr); 104 | } 105 | #endif 106 | tcp_arg(pcb, NULL); 107 | tcp_poll(pcb, NULL, 0); 108 | tcp_sent(pcb, NULL); 109 | if (arg != NULL) { 110 | mem_free(arg); 111 | } 112 | } 113 | } 114 | 115 | static err_t ICACHE_FLASH_ATTR 116 | netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 117 | { 118 | struct netio_state *ns = arg; 119 | u8_t * data_ptr; 120 | u32_t data_cntr; 121 | struct pbuf *q = p; 122 | u16_t len; 123 | 124 | if (p != NULL) { 125 | tcp_recved(pcb, p->tot_len); 126 | } 127 | 128 | if (err == ERR_OK && q != NULL) { 129 | 130 | while (q != NULL) { 131 | data_cntr = q->len; 132 | data_ptr = q->payload; 133 | while (data_cntr--) { 134 | if (ns->state == NETIO_STATE_DONE){ 135 | netio_close(ns, pcb); 136 | break; 137 | } else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) { 138 | if (ns->cntr < 4) { 139 | /* build up the CMD field */ 140 | ns->cmd <<= 8; 141 | ns->cmd |= *data_ptr++; 142 | ns->cntr++; 143 | } else if (ns->cntr < 8) { 144 | /* build up the DATA field */ 145 | ns->data_len <<= 8; 146 | ns->data_len |= *data_ptr++; 147 | ns->cntr++; 148 | 149 | if (ns->cntr == 8) { 150 | /* now we have full command and data words */ 151 | ns->cntr = 0; 152 | ns->buf_pos = 0; 153 | ns->buf_ptr[0] = 0; 154 | if (ns->cmd == NETIO_CMD_C2S) { 155 | ns->state = NETIO_STATE_RECV_DATA; 156 | } else if (ns->cmd == NETIO_CMD_S2C) { 157 | ns->state = NETIO_STATE_SEND_DATA; 158 | /* start timer */ 159 | ns->time_stamp = sys_now(); 160 | /* send first round of data */ 161 | 162 | len = tcp_sndbuf(pcb); 163 | len = LWIP_MIN(len, ns->data_len - ns->cntr); 164 | len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); 165 | 166 | do { 167 | err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); 168 | if (err == ERR_MEM) { 169 | len /= 2; 170 | } 171 | } while ((err == ERR_MEM) && (len > 1)); 172 | 173 | ns->buf_pos += len; 174 | ns->cntr += len; 175 | 176 | } else { 177 | /* unrecognized command, punt */ 178 | ns->cntr = 0; 179 | ns->buf_pos = 0; 180 | ns->buf_ptr[0] = 0; 181 | netio_close(ns, pcb); 182 | break; 183 | } 184 | } 185 | } else { 186 | /* in trouble... shouldn't be in this state! */ 187 | } 188 | 189 | } else if (ns->state == NETIO_STATE_RECV_DATA) { 190 | 191 | if(ns->cntr == 0){ 192 | /* save the first byte of this new round of data 193 | * this will not match ns->buf_ptr[0] in the case that 194 | * NETIO_BUF_SIZE is less than ns->data_len. 195 | */ 196 | ns->first_byte = *data_ptr; 197 | } 198 | 199 | ns->buf_ptr[ns->buf_pos++] = *data_ptr++; 200 | ns->cntr++; 201 | 202 | if (ns->buf_pos == NETIO_BUF_SIZE) { 203 | /* circularize the buffer */ 204 | ns->buf_pos = 0; 205 | } 206 | 207 | if(ns->cntr == ns->data_len){ 208 | ns->cntr = 0; 209 | if (ns->first_byte != 0) { 210 | /* if this last round did not start with 0, 211 | * go look for another command */ 212 | ns->state = NETIO_STATE_WAIT_FOR_CMD; 213 | ns->data_len = 0; 214 | ns->cmd = 0; 215 | /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ 216 | } else { 217 | /* stay here and wait on more data */ 218 | } 219 | } 220 | 221 | } else if (ns->state == NETIO_STATE_SEND_DATA 222 | || ns->state == NETIO_STATE_SEND_DATA_LAST) { 223 | /* I don't think this should happen... */ 224 | } else { 225 | /* done / quit */ 226 | netio_close(ns, pcb); 227 | break; 228 | } /* end of ns->state condition */ 229 | } /* end of while data still in this pbuf */ 230 | 231 | q = q->next; 232 | } 233 | 234 | pbuf_free(p); 235 | 236 | } else { 237 | 238 | /* error or closed by other side */ 239 | if (p != NULL) { 240 | pbuf_free(p); 241 | } 242 | 243 | /* close the connection */ 244 | netio_close(ns, pcb); 245 | 246 | } 247 | return ERR_OK; 248 | 249 | } 250 | 251 | static err_t ICACHE_FLASH_ATTR 252 | netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) 253 | { 254 | struct netio_state *ns = arg; 255 | err_t err = ERR_OK; 256 | 257 | if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { 258 | /* done with this round of sending */ 259 | ns->buf_pos = 0; 260 | ns->cntr = 0; 261 | 262 | /* check if timer expired */ 263 | if (sys_now() - ns->time_stamp > 600) { 264 | ns->buf_ptr[0] = 1; 265 | ns->state = NETIO_STATE_SEND_DATA_LAST; 266 | } else { 267 | ns->buf_ptr[0] = 0; 268 | } 269 | } 270 | 271 | if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ 272 | len = tcp_sndbuf(pcb); 273 | len = LWIP_MIN(len, ns->data_len - ns->cntr); 274 | len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); 275 | 276 | if(ns->cntr < ns->data_len){ 277 | do { 278 | err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); 279 | if (err == ERR_MEM) { 280 | len /= 2; 281 | } 282 | } while ((err == ERR_MEM) && (len > 1)); 283 | 284 | ns->buf_pos += len; 285 | if(ns->buf_pos >= NETIO_BUF_SIZE){ 286 | ns->buf_pos = 0; 287 | } 288 | 289 | ns->cntr += len; 290 | } 291 | } 292 | 293 | if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){ 294 | /* we have buffered up all our data to send this last round, go look for a command */ 295 | ns->state = NETIO_STATE_WAIT_FOR_CMD; 296 | ns->cntr = 0; 297 | /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ 298 | } 299 | 300 | return ERR_OK; 301 | } 302 | 303 | static err_t ICACHE_FLASH_ATTR 304 | netio_poll(void *arg, struct tcp_pcb *pcb) 305 | { 306 | struct netio_state * ns = arg; 307 | if(ns->state == NETIO_STATE_SEND_DATA){ 308 | 309 | } else if(ns->state == NETIO_STATE_DONE){ 310 | netio_close(ns, pcb); 311 | } 312 | 313 | return ERR_OK; 314 | 315 | } 316 | 317 | #if NETIO_USE_STATIC_BUF == 1 318 | static u8_t netio_buf[NETIO_BUF_SIZE]; 319 | #endif 320 | 321 | static err_t ICACHE_FLASH_ATTR 322 | netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) 323 | { 324 | struct netio_state * ns; 325 | 326 | LWIP_UNUSED_ARG(err); 327 | 328 | ns = (struct netio_state *)mem_malloc(sizeof(struct netio_state)); 329 | 330 | if(ns == NULL){ 331 | return ERR_MEM; 332 | } 333 | 334 | ns->state = NETIO_STATE_WAIT_FOR_CMD; 335 | ns->data_len = 0; 336 | ns->cmd = 0; 337 | ns->cntr = 0; 338 | ns->buf_pos = 0; 339 | #if NETIO_USE_STATIC_BUF == 1 340 | ns->buf_ptr = netio_buf; 341 | #else 342 | ns->buf_ptr = (u8_t *)mem_malloc(NETIO_BUF_SIZE); 343 | 344 | if(ns->buf_ptr == NULL){ 345 | mem_free(ns); 346 | return ERR_MEM; 347 | } 348 | #endif 349 | 350 | ns->buf_ptr[0] = 0; 351 | 352 | tcp_arg(pcb, ns); 353 | tcp_sent(pcb, netio_sent); 354 | tcp_recv(pcb, netio_recv); 355 | tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */ 356 | return ERR_OK; 357 | } 358 | 359 | void ICACHE_FLASH_ATTR netio_init(void) 360 | { 361 | struct tcp_pcb *pcb; 362 | 363 | pcb = tcp_new(); 364 | tcp_bind(pcb, IP_ADDR_ANY, 18767); 365 | pcb = tcp_listen(pcb); 366 | tcp_accept(pcb, netio_accept); 367 | } 368 | 369 | #endif /* LWIP_TCP */ 370 | -------------------------------------------------------------------------------- /third-party/lwip-espressif-contributed/ping.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Ping sender module 4 | * 5 | */ 6 | 7 | /* 8 | * Redistribution and use in source and binary forms, with or without modification, 9 | * are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 3. The name of the author may not be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 28 | * OF SUCH DAMAGE. 29 | * 30 | * This file is part of the lwIP TCP/IP stack. 31 | * 32 | */ 33 | 34 | /** 35 | * This is an example of a "ping" sender (with raw API and socket API). 36 | * It can be used as a start point to maintain opened a network connection, or 37 | * like a network "watchdog" for your device. 38 | * 39 | */ 40 | 41 | /* 42 | * copyright (c) 2010 - 2011 Espressif System 43 | */ 44 | 45 | #include "lwip/opt.h" 46 | 47 | #if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ 48 | 49 | #include "lwip/mem.h" 50 | #include "lwip/raw.h" 51 | #include "lwip/icmp.h" 52 | #include "lwip/netif.h" 53 | #include "lwip/sys.h" 54 | #include "lwip/timers.h" 55 | #include "lwip/inet_chksum.h" 56 | #include "os_type.h" 57 | #include "osapi.h" 58 | 59 | #include "lwip/app/ping.h" 60 | 61 | #if PING_USE_SOCKETS 62 | #include "lwip/sockets.h" 63 | #include "lwip/inet.h" 64 | #endif /* PING_USE_SOCKETS */ 65 | 66 | #ifdef MEMLEAK_DEBUG 67 | static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; 68 | #endif 69 | 70 | /* ping variables */ 71 | static u16_t ping_seq_num = 0; 72 | static u32_t ping_time; 73 | static struct ping_msg *ping_list = NULL; 74 | 75 | static void ping_coarse_tmr(void *arg); 76 | static void ping_result_tmr(void *arg); 77 | 78 | static void ping_raw_stop(void) 79 | { 80 | if (ping_list) { 81 | sys_untimeout(ping_result_tmr, ping_list); 82 | raw_remove(ping_list->ping_pcb); 83 | os_free(ping_list); 84 | ping_list = NULL; 85 | } 86 | } 87 | 88 | static void ping_raw_start(struct ping_msg *pingmsg) 89 | { 90 | ping_list = pingmsg; 91 | } 92 | 93 | static void ping_result_tmr(void *arg) 94 | { 95 | ping_raw_stop(); 96 | } 97 | 98 | static void ping_prepare_result(void *arg) 99 | { 100 | struct ping_msg *pingmsg = (struct ping_msg*)arg; 101 | struct ping_option *ping_opt = NULL; 102 | struct ping_resp pingresp; 103 | ip_addr_t ping_target; 104 | 105 | ping_opt = pingmsg->ping_opt; 106 | if (pingmsg->sent_count == 1) { 107 | sys_untimeout(ping_coarse_tmr, pingmsg); 108 | 109 | uint32 delay = system_relative_time(pingmsg->ping_start); 110 | delay /= PING_COARSE; 111 | if (ping_opt->sent_function == NULL) { 112 | os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n", pingmsg->max_count, pingmsg->timeout_count, 113 | PING_DATA_SIZE * (pingmsg->max_count - pingmsg->timeout_count), delay); 114 | } else { 115 | os_bzero(&pingresp, sizeof(struct ping_resp)); 116 | pingresp.total_count = pingmsg->max_count; 117 | pingresp.timeout_count = pingmsg->timeout_count; 118 | pingresp.total_bytes = PING_DATA_SIZE * (pingmsg->max_count - pingmsg->timeout_count); 119 | pingresp.total_time = delay; 120 | pingresp.ping_err = 0; 121 | } 122 | 123 | if (ping_opt->sent_function != NULL) 124 | ping_opt->sent_function(ping_opt, (uint8*) &pingresp); 125 | 126 | sys_timeout(0, ping_result_tmr, pingmsg); 127 | } 128 | } 129 | 130 | static void ping_timeout(void* arg) 131 | { 132 | struct ping_msg *pingmsg = (struct ping_msg *)arg; 133 | pingmsg->timeout_count ++; 134 | if (pingmsg->ping_opt->recv_function == NULL){ 135 | os_printf("ping timeout\n"); 136 | } else { 137 | struct ping_resp pingresp; 138 | os_bzero(&pingresp, sizeof(struct ping_resp)); 139 | pingresp.ping_err = -1; 140 | pingmsg->ping_opt->recv_function(pingmsg->ping_opt, (void*)&pingresp); 141 | } 142 | 143 | ping_prepare_result(pingmsg); 144 | } 145 | 146 | /** Prepare a echo ICMP request */ 147 | static void 148 | ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) 149 | { 150 | size_t i = 0; 151 | size_t data_len = len - sizeof(struct icmp_echo_hdr); 152 | 153 | ICMPH_TYPE_SET(iecho, ICMP_ECHO); 154 | ICMPH_CODE_SET(iecho, 0); 155 | iecho->chksum = 0; 156 | iecho->id = PING_ID; 157 | ++ ping_seq_num; 158 | if (ping_seq_num == 0x7fff) 159 | ping_seq_num = 0; 160 | 161 | iecho->seqno = htons(ping_seq_num); 162 | 163 | /* fill the additional data buffer with some data */ 164 | for(i = 0; i < data_len; i++) { 165 | ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; 166 | } 167 | 168 | iecho->chksum = inet_chksum(iecho, len); 169 | } 170 | 171 | static void 172 | ping_prepare_er(struct icmp_echo_hdr *iecho, u16_t len) 173 | { 174 | 175 | ICMPH_TYPE_SET(iecho, ICMP_ER); 176 | ICMPH_CODE_SET(iecho, 0); 177 | iecho->chksum = 0; 178 | 179 | iecho->chksum = inet_chksum(iecho, len); 180 | } 181 | 182 | /* Ping using the raw ip */ 183 | static u8_t 184 | ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr) 185 | { 186 | struct icmp_echo_hdr *iecho = NULL; 187 | static u16_t seqno = 0; 188 | struct ping_msg *pingmsg = (struct ping_msg*)arg; 189 | 190 | LWIP_UNUSED_ARG(arg); 191 | LWIP_UNUSED_ARG(pcb); 192 | LWIP_UNUSED_ARG(addr); 193 | LWIP_ASSERT("p != NULL", p != NULL); 194 | 195 | if (pbuf_header( p, -PBUF_IP_HLEN)==0) { 196 | iecho = (struct icmp_echo_hdr *)p->payload; 197 | 198 | if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num)) && iecho->type == ICMP_ER) { 199 | LWIP_DEBUGF( PING_DEBUG, ("ping: recv ")); 200 | ip_addr_debug_print(PING_DEBUG, addr); 201 | LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", (sys_now()-ping_time))); 202 | if (iecho->seqno != seqno){ 203 | /* do some ping result processing */ 204 | { 205 | struct ip_hdr *iphdr = NULL; 206 | char ipaddrstr[16]; 207 | ip_addr_t source_ip; 208 | sys_untimeout(ping_timeout, pingmsg); 209 | os_bzero(&source_ip, sizeof(ip_addr_t)); 210 | os_bzero(ipaddrstr, sizeof(ipaddrstr)); 211 | uint32 delay = system_relative_time(pingmsg->ping_sent); 212 | delay /= PING_COARSE; 213 | iphdr = (struct ip_hdr*)((u8*)iecho - PBUF_IP_HLEN); 214 | source_ip.addr = iphdr->src.addr; 215 | ipaddr_ntoa_r(&source_ip,ipaddrstr, sizeof(ipaddrstr)); 216 | if (pingmsg->ping_opt->recv_function == NULL){ 217 | os_printf("recv %s: byte = %d, time = %d ms, seq = %d\n",ipaddrstr, PING_DATA_SIZE, delay, ntohs(iecho->seqno)); 218 | } else { 219 | struct ping_resp pingresp; 220 | os_bzero(&pingresp, sizeof(struct ping_resp)); 221 | pingresp.bytes = PING_DATA_SIZE; 222 | pingresp.resp_time = delay; 223 | pingresp.seqno = ntohs(iecho->seqno); 224 | pingresp.ping_err = 0; 225 | pingmsg->ping_opt->recv_function(pingmsg->ping_opt,(void*) &pingresp); 226 | } 227 | ping_prepare_result(pingmsg); 228 | } 229 | seqno = iecho->seqno; 230 | } 231 | 232 | PING_RESULT(1); 233 | pbuf_free(p); 234 | return 1; /* eat the packet */ 235 | } 236 | } 237 | 238 | return 0; /* don't eat the packet */ 239 | } 240 | 241 | static void 242 | ping_send(struct raw_pcb *raw, ip_addr_t *addr) 243 | { 244 | struct pbuf *p = NULL; 245 | struct icmp_echo_hdr *iecho = NULL; 246 | size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE; 247 | 248 | LWIP_DEBUGF( PING_DEBUG, ("ping: send ")); 249 | ip_addr_debug_print(PING_DEBUG, addr); 250 | LWIP_DEBUGF( PING_DEBUG, ("\n")); 251 | LWIP_ASSERT("ping_size <= 0xffff", ping_size <= 0xffff); 252 | 253 | p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM); 254 | if (!p) { 255 | return; 256 | } 257 | if ((p->len == p->tot_len) && (p->next == NULL)) { 258 | iecho = (struct icmp_echo_hdr *)p->payload; 259 | 260 | ping_prepare_echo(iecho, (u16_t)ping_size); 261 | 262 | raw_sendto(raw, p, addr); 263 | ping_time = sys_now(); 264 | } 265 | pbuf_free(p); 266 | } 267 | 268 | static void 269 | ping_coarse_tmr(void *arg) 270 | { 271 | struct ping_msg *pingmsg = (struct ping_msg*)arg; 272 | struct ping_option *ping_opt= NULL; 273 | struct ping_resp pingresp; 274 | ip_addr_t ping_target; 275 | 276 | LWIP_ASSERT("ping_timeout: no pcb given!", pingmsg != NULL); 277 | ping_target.addr = pingmsg->ping_opt->ip; 278 | ping_opt = pingmsg->ping_opt; 279 | if (--pingmsg->sent_count != 0){ 280 | pingmsg ->ping_sent = system_get_time(); 281 | ping_send(pingmsg->ping_pcb, &ping_target); 282 | 283 | sys_timeout(PING_TIMEOUT_MS, ping_timeout, pingmsg); 284 | sys_timeout(pingmsg->coarse_time, ping_coarse_tmr, pingmsg); 285 | } else { 286 | uint32 delay = system_relative_time(pingmsg->ping_start); 287 | delay /= PING_COARSE; 288 | // ping_seq_num = 0; 289 | if (ping_opt->sent_function == NULL){ 290 | os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n", 291 | pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay); 292 | } else { 293 | os_bzero(&pingresp, sizeof(struct ping_resp)); 294 | pingresp.total_count = pingmsg->max_count; 295 | pingresp.timeout_count = pingmsg->timeout_count; 296 | pingresp.total_bytes = PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count); 297 | pingresp.total_time = delay; 298 | pingresp.ping_err = 0; 299 | } 300 | sys_untimeout(ping_coarse_tmr, pingmsg); 301 | raw_remove(pingmsg->ping_pcb); 302 | os_free(pingmsg); 303 | if (ping_opt->sent_function != NULL) 304 | ping_opt->sent_function(ping_opt,(uint8*)&pingresp); 305 | } 306 | } 307 | 308 | static bool 309 | ping_raw_init(struct ping_msg *pingmsg) 310 | { 311 | if (pingmsg == NULL) 312 | return false; 313 | 314 | ip_addr_t ping_target; 315 | pingmsg->ping_pcb = raw_new(IP_PROTO_ICMP); 316 | LWIP_ASSERT("ping_pcb != NULL", pingmsg->ping_pcb != NULL); 317 | 318 | raw_recv(pingmsg->ping_pcb, ping_recv, pingmsg); 319 | raw_bind(pingmsg->ping_pcb, IP_ADDR_ANY); 320 | 321 | ping_target.addr = pingmsg->ping_opt->ip; 322 | pingmsg ->ping_sent = system_get_time(); 323 | ping_send(pingmsg->ping_pcb, &ping_target); 324 | 325 | ping_raw_start(pingmsg); 326 | sys_timeout(PING_TIMEOUT_MS, ping_timeout, pingmsg); 327 | sys_timeout(pingmsg->coarse_time, ping_coarse_tmr, pingmsg); 328 | return true; 329 | } 330 | 331 | bool 332 | ping_start(struct ping_option *ping_opt) 333 | { 334 | struct ping_msg *pingmsg = NULL; 335 | ping_raw_stop(); 336 | pingmsg = (struct ping_msg *)os_zalloc(sizeof(struct ping_msg)); 337 | if (pingmsg == NULL || ping_opt == NULL) 338 | return false; 339 | 340 | pingmsg->ping_opt = ping_opt; 341 | if (ping_opt->count != 0) 342 | pingmsg->max_count = ping_opt->count; 343 | else 344 | pingmsg->max_count = DEFAULT_PING_MAX_COUNT; 345 | 346 | if (ping_opt->coarse_time != 0) 347 | pingmsg->coarse_time = ping_opt->coarse_time * PING_COARSE; 348 | else 349 | pingmsg->coarse_time = PING_COARSE; 350 | 351 | pingmsg->ping_start = system_get_time(); 352 | pingmsg->sent_count = pingmsg->max_count; 353 | return ping_raw_init(pingmsg); 354 | } 355 | 356 | bool 357 | ping_regist_recv(struct ping_option *ping_opt, ping_recv_function ping_recv) 358 | { 359 | if (ping_opt == NULL) 360 | return false; 361 | 362 | ping_opt ->recv_function = ping_recv; 363 | return true; 364 | } 365 | 366 | bool 367 | ping_regist_sent(struct ping_option *ping_opt, ping_sent_function ping_sent) 368 | { 369 | if (ping_opt == NULL) 370 | return false; 371 | 372 | ping_opt ->sent_function = ping_sent; 373 | return true; 374 | } 375 | 376 | #endif /* LWIP_RAW */ 377 | -------------------------------------------------------------------------------- /display_cfa634.c: -------------------------------------------------------------------------------- 1 | #include "display.h" 2 | #include "display_cfa634.h" 3 | #include "config.h" 4 | #include "io.h" 5 | #include "io_gpio.h" 6 | #include "uart.h" 7 | #include "sys_time.h" 8 | 9 | #include 10 | #include 11 | 12 | typedef struct 13 | { 14 | unsigned int unicode; 15 | unsigned int internal; 16 | } unicode_map_t; 17 | 18 | typedef struct 19 | { 20 | unsigned int unicode; 21 | unsigned int internal; 22 | unsigned int pattern[8]; 23 | } udg_map_t; 24 | 25 | enum 26 | { 27 | display_text_width = 20, 28 | display_text_height = 4, 29 | 30 | command_escape_2 = 0x01, 31 | command_restore = 0x03, 32 | command_contrast = 0x0f, 33 | command_goto = 0x11, 34 | command_scroll_off = 0x14, 35 | command_wrap_off = 0x18, 36 | command_escape_1 = 0x1e, 37 | 38 | mapeof = 0xffffffff, 39 | }; 40 | 41 | roflash static const unicode_map_t unicode_map[] = 42 | { 43 | { 0x0024, 0xa2 }, // $ 44 | { 0x0040, 0xa0 }, // @ 45 | { 0x005b, 0xfa }, // [ 46 | { 0x005c, 0xfb }, // backslash 47 | { 0x005d, 0xfc }, // ] 48 | { 0x005e, 0x0d }, // ^ 49 | { 0x005f, 0xc4 }, // _ 50 | { 0x0060, 0x87 }, // ` 51 | { 0x007b, 0xfd }, // { 52 | { 0x007c, 0xfe }, // | 53 | { 0x007d, 0xff }, // } 54 | { 0x007e, 0xce }, // ~ 55 | { 0x007f, 0xd6 }, // del 56 | { 0x25b6, 0x10 }, // ▶ 57 | { 0x25c0, 0x11 }, // ◀ 58 | { 0x00ab, 0x14 }, // « 59 | { 0x00bb, 0x15 }, // » 60 | { 0x2196, 0x16 }, // ↖ 61 | { 0x2197, 0x17 }, // ↗ 62 | { 0x2199, 0x18 }, // ↙ 63 | { 0x2198, 0x19 }, // ↘ 64 | { 0x25b2, 0x1a }, // ▲ 65 | { 0x25bc, 0x1b }, // ▼ 66 | { 0x23ce, 0x1c }, // ⏎ 67 | { 0x258b, 0x1f }, // ▋ 68 | { 0x00a4, 0x24 }, // ¤ 69 | { 0x00a1, 0x40 }, // ¡ 70 | { 0x00c4, 0x5b }, // Ä 71 | { 0x00d6, 0x5c }, // Ö 72 | { 0x00d1, 0x5d }, // Ñ 73 | { 0x00dc, 0x5e }, // Ü 74 | { 0x00a7, 0x5f }, // § 75 | { 0x00bf, 0x60 }, // ¿ 76 | { 0x00e4, 0x7b }, // ä 77 | { 0x00f6, 0x7c }, // ö 78 | { 0x00f1, 0x7d }, // ñ 79 | { 0x00fc, 0x7e }, // ü 80 | { 0x00e0, 0x7f }, // à 81 | { 0x2070, 0x80 }, // ⁰ 82 | { 0x00b9, 0x81 }, // ¹ 83 | { 0x00b2, 0x82 }, // ² 84 | { 0x00b3, 0x83 }, // ³ 85 | { 0x2074, 0x84 }, // ⁴ 86 | { 0x2075, 0x85 }, // ⁵ 87 | { 0x2076, 0x86 }, // ⁶ 88 | { 0x2077, 0x87 }, // ⁷ 89 | { 0x2078, 0x88 }, // ⁸ 90 | { 0x2079, 0x89 }, // ⁹ 91 | { 0x00bd, 0x8a }, // ½ 92 | { 0x00bc, 0x8b }, // ¼ 93 | { 0x00b1, 0x8c }, // ± 94 | { 0x2265, 0x8d }, // ≥ 95 | { 0x2264, 0x8e }, // ≤ 96 | { 0x00b5, 0x8f }, // µ 97 | { 0x03bc, 0x8f }, // μ 98 | { 0x266a, 0x90 }, // ♪ 99 | { 0x266b, 0x91 }, // ♫ 100 | { 0x1f514,0x92 }, // 🔔 101 | { 0x1f56d,0x92 }, // 🕭 102 | { 0x2665, 0x93 }, // ♥ 103 | { 0x25c6, 0x94 }, // ◆ 104 | { 0x1f4f6,0x95 }, // 📶 105 | { 0x201c, 0x98 }, // “ 106 | { 0x201d, 0x99 }, // ” 107 | { 0x03b1, 0x9c }, // α 108 | { 0x03b5, 0x9d }, // ε 109 | { 0x03b4, 0x9e }, // δ 110 | { 0x221e, 0x9f }, // ∞ 111 | { 0x00a3, 0xa1 }, // £ 112 | { 0x00a5, 0xa3 }, // ¥ 113 | { 0x00e8, 0xa4 }, // è 114 | { 0x00e9, 0xa5 }, // é 115 | { 0x00f9, 0xa6 }, // ù 116 | { 0x00ec, 0xa7 }, // ì 117 | { 0x00f2, 0xa8 }, // ò 118 | { 0x00e7, 0xa9 }, // ç 119 | { 0x00d8, 0xab }, // Ø 120 | { 0x00f8, 0xac }, // ø 121 | { 0x0226, 0xae }, // Ȧ 122 | { 0x0227, 0xaf }, // ȧ 123 | { 0x00a2, 0xb1 }, // ¢ 124 | { 0x03c4, 0xb3 }, // τ 125 | { 0x03bb, 0xb4 }, // λ 126 | { 0x03a9, 0xb5 }, // Ω 127 | { 0x03c0, 0xb6 }, // π 128 | { 0x03a8, 0xb7 }, // Ψ 129 | { 0x03a3, 0xb8 }, // Σ 130 | { 0x03b8, 0xb9 }, // θ 131 | { 0x039e, 0xba }, // Ξ 132 | { 0x25cf, 0xbb }, // ● 133 | { 0x00c6, 0xbc }, // Æ 134 | { 0x00e6, 0xbd }, // æ 135 | { 0x03b2, 0xbe }, // β 136 | { 0x00c9, 0xbf }, // É 137 | { 0x0393, 0xc0 }, // Γ 138 | { 0x039b, 0xc1 }, // Λ 139 | { 0x03a0, 0xc2 }, // Π 140 | { 0x03d2, 0xc3 }, // ϒ 141 | { 0x00c8, 0xc5 }, // È 142 | { 0x00ca, 0xc6 }, // Ê 143 | { 0x00ea, 0xc7 }, // ê 144 | { 0x00e7, 0xc8 }, // ç 145 | { 0x25c7, 0xcf }, // ◇ 146 | { 0x258b, 0xd0 }, // ▋ 147 | { 0x258c, 0xd1 }, // ▌ 148 | { 0x258d, 0xd2 }, // ▍ 149 | { 0x258e, 0xd3 }, // ▎ 150 | { 0x258f, 0xd4 }, // ▏ 151 | { 0x258b, 0xd6 }, // ▋ 152 | { 0x258c, 0xd7 }, // ▌ 153 | { 0x258d, 0xd8 }, // ▍ 154 | { 0x258e, 0xd9 }, // ▎ 155 | { 0x258f, 0xda }, // ▏ 156 | { 0x20a7, 0xdb }, // ₧ 157 | { 0x2191, 0xde }, // ↑ 158 | { 0x2192, 0xdf }, // → 159 | { 0x2193, 0xe0 }, // ↓ 160 | { 0x2190, 0xe1 }, // ← 161 | { 0x00c1, 0xe2 }, // Á 162 | { 0x00cd, 0xe3 }, // Í 163 | { 0x00d3, 0xe4 }, // Ó 164 | { 0x00da, 0xe5 }, // Ú 165 | { 0x00e1, 0xe7 }, // á 166 | { 0x00ed, 0xe8 }, // í 167 | { 0x00f3, 0xe9 }, // ó 168 | { 0x00fa, 0xea }, // ú 169 | { 0x00d4, 0xec }, // Ô 170 | { 0x00f4, 0xed }, // ô 171 | { mapeof, 0xff }, // EOF 172 | }; 173 | 174 | roflash static const udg_map_t udg_map[] = 175 | { 176 | { 0x00eb, 0, // ë 177 | { 178 | 0b00001010, 179 | 0b00000000, 180 | 0b00001110, 181 | 0b00010001, 182 | 0b00011111, 183 | 0b00010000, 184 | 0b00001110, 185 | 0b00000000, 186 | } 187 | }, 188 | { 0x00ef, 1, // ï 189 | { 190 | 0b00001010, 191 | 0b00000000, 192 | 0b00001100, 193 | 0b00000100, 194 | 0b00000100, 195 | 0b00000100, 196 | 0b00001110, 197 | 0b00000000, 198 | } 199 | }, 200 | { 0x03c3, 2, // σ 201 | { 202 | 0b00000000, 203 | 0b00000011, 204 | 0b00001110, 205 | 0b00010001, 206 | 0b00010001, 207 | 0b00001110, 208 | 0b00000000, 209 | 0b00000000, 210 | } 211 | }, 212 | { 0x03c1, 3, // ρ 213 | { 214 | 0b00000000, 215 | 0b00000000, 216 | 0b00001110, 217 | 0b00010001, 218 | 0b00011110, 219 | 0b00010000, 220 | 0b00010000, 221 | 0b00000000, 222 | } 223 | }, 224 | { 225 | 0x00a9, 4, // © 226 | { 227 | 0b00000100, 228 | 0b00001010, 229 | 0b00010111, 230 | 0b00011001, 231 | 0b00010111, 232 | 0b00001010, 233 | 0b00000100, 234 | 0b00000000, 235 | } 236 | }, 237 | { 238 | 0x20ac, 5, // € 239 | { 240 | 0b00000011, 241 | 0b00000100, 242 | 0b00011111, 243 | 0b00000100, 244 | 0b00011111, 245 | 0b00000100, 246 | 0b00000011, 247 | 0b00000000, 248 | } 249 | }, 250 | { mapeof, 6, // EOF, 251 | { }, 252 | } 253 | }; 254 | 255 | static bool display_setup; 256 | static bool display_logmode; 257 | static unsigned int display_uart; 258 | static unsigned int display_x, display_y; 259 | 260 | static bool attr_result_used text_goto(int x, int y) 261 | { 262 | if(x >= 0) 263 | display_x = x; 264 | 265 | if(y >= 0) 266 | display_y = y; 267 | 268 | if((display_x >= display_text_width) || (display_y >= display_text_height)) 269 | return(true); 270 | 271 | uart_send(display_uart, command_goto); 272 | uart_send(display_uart, display_x); 273 | uart_send(display_uart, display_y); 274 | 275 | uart_flush(display_uart); 276 | 277 | return(true); 278 | } 279 | 280 | static bool attr_result_used text_send(unsigned int byte) 281 | { 282 | if((display_x < display_text_width) && (display_y < display_text_height)) 283 | { 284 | if((byte < ' ') || ((byte >= 128) && (byte <= 135))) 285 | { 286 | uart_send(display_uart, command_escape_1); 287 | uart_send(display_uart, command_escape_2); 288 | } 289 | 290 | uart_send(display_uart, byte); 291 | display_x++; 292 | } 293 | 294 | uart_flush(display_uart); 295 | 296 | return(true); 297 | } 298 | 299 | static attr_result_used bool text_send_ascii_string(const char *string) 300 | { 301 | unsigned int current; 302 | 303 | for(current = 0; string[current]; current++) 304 | if(!text_send(string[current])) 305 | return(false); 306 | 307 | return(true); 308 | } 309 | 310 | static bool attr_result_used text_newline(void) 311 | { 312 | unsigned int x, y, text_width; 313 | 314 | text_width = display_text_width; 315 | 316 | if(display_logmode) 317 | { 318 | y = (display_y + 1) % display_text_height; 319 | 320 | if(!text_goto(0, y)) 321 | return(false); 322 | } 323 | else 324 | { 325 | if(display_y == 0) 326 | text_width = display_text_width - 6; 327 | 328 | y = display_y + 1; 329 | } 330 | 331 | if(display_y < display_text_height) 332 | for(x = display_x; x < text_width; x++) 333 | if(!text_send(' ')) 334 | return(false); 335 | 336 | if(text_width != display_text_width) 337 | { 338 | unsigned int hour, minute; 339 | string_new(, time_date, 32); 340 | 341 | string_clear(&time_date); 342 | time_get(&hour, &minute, 0, 0, 0, 0); 343 | string_format(&time_date, " %02u:%02u", hour, minute); 344 | 345 | if(!text_goto(14, 0)) 346 | return(false); 347 | 348 | if(!text_send_ascii_string(string_to_cstr(&time_date))) 349 | return(false); 350 | } 351 | 352 | if(!text_goto(0, y)) 353 | return(false); 354 | 355 | return(true); 356 | } 357 | 358 | bool display_cfa634_setup(unsigned int io, unsigned int pin) 359 | { 360 | if((io != io_id_gpio) || (pin >= max_pins_per_io)) 361 | return(false); 362 | 363 | display_uart = io_gpio_get_uart_from_pin(pin); 364 | 365 | if((display_uart != 0) && (display_uart != 1)) 366 | return(false); 367 | 368 | display_setup = true; 369 | 370 | return(true); 371 | } 372 | 373 | static attr_const bool bright(int brightness) 374 | { 375 | roflash static const unsigned int values[5] = { 0, 55, 65, 70, 75 }; 376 | 377 | if(!display_setup) 378 | return(false); 379 | 380 | if((brightness < 0) || (brightness > 4)) 381 | return(false); 382 | 383 | uart_send(display_uart, command_contrast); 384 | uart_send(display_uart, values[brightness]); 385 | uart_flush(display_uart); 386 | 387 | return(true); 388 | } 389 | 390 | static bool init(void) 391 | { 392 | const udg_map_t *map; 393 | unsigned int baudrate, ix, byte; 394 | 395 | if(!display_setup) 396 | return(false); 397 | 398 | if(!config_get_uint("cfa634.baud", &baudrate, -1, -1)) 399 | return(false); 400 | 401 | uart_baudrate(display_uart, baudrate); 402 | uart_data_bits(display_uart, 8); 403 | uart_stop_bits(display_uart, 1); 404 | uart_parity(display_uart, parity_none); 405 | 406 | for(map = udg_map, ix = 0; map->unicode != mapeof; map++, ix++) 407 | { 408 | uart_send(display_uart, 25); // send UDG 409 | uart_send(display_uart, map->internal); 410 | 411 | uart_flush(display_uart); 412 | msleep(1); 413 | 414 | for(byte = 0; byte < 8; byte++) 415 | { 416 | uart_send(display_uart, map->pattern[byte] & 0xff); 417 | uart_flush(display_uart); 418 | msleep(1); 419 | } 420 | } 421 | 422 | return(bright(1)); 423 | } 424 | 425 | static bool begin(unsigned int slot, bool logmode) 426 | { 427 | uart_send(display_uart, command_restore); 428 | uart_send(display_uart, command_scroll_off); 429 | uart_send(display_uart, command_wrap_off); 430 | 431 | display_logmode = logmode; 432 | 433 | if(!text_goto(0, 0)) 434 | return(false); 435 | 436 | uart_flush(display_uart); 437 | 438 | return(true); 439 | } 440 | 441 | static bool output(unsigned int length, const unsigned int unicode[]) 442 | { 443 | const unicode_map_t *unicode_map_ptr; 444 | const udg_map_t *udg_map_ptr; 445 | unsigned int current_index, current; 446 | 447 | for(current_index = 0; current_index < length; current_index++) 448 | { 449 | current = unicode[current_index]; 450 | 451 | if(current == '\n') 452 | { 453 | if(!text_newline()) 454 | return(false); 455 | 456 | continue; 457 | } 458 | 459 | if((display_y < display_text_height) && (display_x < display_text_width)) 460 | { 461 | for(unicode_map_ptr = unicode_map; unicode_map_ptr->unicode != mapeof; unicode_map_ptr++) 462 | if(unicode_map_ptr->unicode == current) 463 | { 464 | if(!text_send(unicode_map_ptr->internal)) 465 | return(false); 466 | 467 | continue; 468 | } 469 | 470 | for(udg_map_ptr = udg_map; udg_map_ptr->unicode != mapeof; udg_map_ptr++) 471 | if((udg_map_ptr->unicode == current)) 472 | { 473 | if(!text_send(udg_map_ptr->internal)) 474 | return(false); 475 | 476 | continue; 477 | } 478 | 479 | if((current < ' ') || (current > '}')) 480 | current = ' '; 481 | 482 | uart_send(display_uart, current); 483 | } 484 | } 485 | 486 | return(true); 487 | } 488 | 489 | static bool end(void) 490 | { 491 | while(display_y < display_text_height) 492 | if(!text_newline()) 493 | break; 494 | 495 | uart_flush(display_uart); 496 | 497 | return(true); 498 | } 499 | 500 | roflash const char help_description_display_cfa634[] = "> usage: dc6 \n"; 501 | 502 | app_action_t application_function_display_cfa634(app_params_t *parameters) 503 | { 504 | unsigned int baudrate; 505 | 506 | baudrate = 0; 507 | 508 | if(parse_uint(1, parameters->src, &baudrate, 0, ' ') == parse_ok) 509 | { 510 | if(!config_open_write()) 511 | goto config_error; 512 | 513 | if(baudrate == 0) 514 | config_delete("cfa634.", true, -1, -1); 515 | else 516 | if(!config_set_uint("cfa634.baud", baudrate, -1, -1)) 517 | goto config_error; 518 | 519 | if(!config_close_write()) 520 | goto config_error; 521 | } 522 | 523 | if(!config_get_uint("cfa634.baud", &baudrate, -1, -1)) 524 | { 525 | string_format(parameters->dst, "no cfa634 display configured\n"); 526 | return(app_action_error); 527 | } 528 | 529 | string_format(parameters->dst, "cfa634: baud rate: %u\n", baudrate); 530 | 531 | return(app_action_normal); 532 | 533 | config_error: 534 | config_abort_write(); 535 | string_clear(parameters->dst); 536 | string_append(parameters->dst, "> cannot set config\n"); 537 | return(app_action_error); 538 | } 539 | 540 | static bool info(display_info_t *infostruct) 541 | { 542 | strncpy(infostruct->name, "CrystalFontz CFA634", sizeof(infostruct->name)); 543 | 544 | infostruct->columns = 20; 545 | infostruct->rows = 4; 546 | infostruct->cell_width = 0; 547 | infostruct->cell_height = 0; 548 | infostruct->width = 0; 549 | infostruct->height = 0; 550 | infostruct->pixel_mode = display_pixel_mode_none; 551 | 552 | return(true); 553 | } 554 | 555 | roflash const display_hooks_t display_hooks_cfa = 556 | { 557 | init, 558 | info, 559 | begin, 560 | output, 561 | end, 562 | bright, 563 | (void *)0, 564 | (void *)0, 565 | (void *)0, 566 | (void *)0, 567 | }; 568 | --------------------------------------------------------------------------------