aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMitch Bradley <wmb@firmworks.com>2019-08-27 12:57:38 -1000
committerMitch Bradley <wmb@firmworks.com>2019-08-27 13:07:02 -1000
commit980fd1b9a458b89f8481bb270e630f839aa35880 (patch)
tree506534092ccb9a53760a63376f1226b1a0f0055c
parentc176837261d5e4a408302d85b7b8eceb25ae6cd9 (diff)
downloadcforth-980fd1b9a458b89f8481bb270e630f839aa35880.tar.gz
Initial revision
-rw-r--r--build/remote/Makefile22
-rw-r--r--src/app/remote/app.fth138
-rw-r--r--src/app/remote/extend.c860
3 files changed, 1020 insertions, 0 deletions
diff --git a/build/remote/Makefile b/build/remote/Makefile
new file mode 100644
index 0000000..47f57ae
--- /dev/null
+++ b/build/remote/Makefile
@@ -0,0 +1,22 @@
+# Builds CForth for ESP8266 with memote control code
+
+TOPDIR=../..
+UPDIR=$(realpath $(TOPDIR)/..)
+
+# CONFIG += -DBITS32 -DT16
+CONFIG += -DBITS32
+
+CFLAGS += -m32
+
+CC := gcc
+
+# Change these to reflect the locations of external stuff on your system,
+# either here or on the command line, e.g. COMPORT=COM27 make download
+SDK_PARENT_PATH ?= $(UPDIR)
+NODEMCU_PARENT_PATH ?= $(UPDIR)
+COMPORT ?= COM36
+
+APPPATH = $(TOPDIR)/src/app/remote
+VPATH += $(APPPATH)
+
+include $(TOPDIR)/src/app/esp8266/targets.mk
diff --git a/src/app/remote/app.fth b/src/app/remote/app.fth
new file mode 100644
index 0000000..8be28ef
--- /dev/null
+++ b/src/app/remote/app.fth
@@ -0,0 +1,138 @@
+\ Load file for application-specific Forth extensions
+\ This particular one is sort of a "kitchen sink" build
+\ with a bunch of drivers for various sensors.
+
+fl ../esp8266/common.fth
+fl ../../lib/random.fth
+
+also modem
+: rx ( -- ) pad unused pad here - - (receive) #100 ms ;
+previous
+
+2 constant wakeup-pin
+\ In conjunction with external circuitry, this prevents
+\ the RST line from being driven while the app is operational.
+\ That allows the activation buttons to be diode-or'ed into
+\ the RST line to wakeup from deep sleep
+: init-wakeup ( -- )
+ false gpio-output wakeup-pin gpio-mode
+ 1 wakeup-pin gpio-pin!
+;
+
+1 constant ir-pin
+
+: init-ir ( -- )
+ false gpio-output ir-pin gpio-mode
+ 0 ir-pin gpio-pin!
+;
+
+fl ../esp8266/gpio-switch.fth
+
+7 constant projector-switch-pin
+6 constant down-switch-pin
+5 constant up-switch-pin
+: init-switches ( -- )
+ projector-switch-pin init-gpio-switch
+ up-switch-pin init-gpio-switch
+ down-switch-pin init-gpio-switch
+;
+
+4 constant led-pin
+: init-led ( -- ) false gpio-output led-pin gpio-mode ;
+: led-on ( -- ) 0 led-pin gpio-pin! ;
+: led-off ( -- ) 1 led-pin gpio-pin! ;
+: blips ( -- ) led-on #100 ms led-off #100 ms led-on #100 ms led-off ;
+: projector-switch? ( -- flag ) projector-switch-pin gpio-pin@ 0= ;
+: up-switch? ( -- flag ) up-switch-pin gpio-pin@ 0= ;
+: down-switch? ( -- flag ) down-switch-pin gpio-pin@ 0= ;
+
+$c1aa09f6 value projector-on/off
+$00ffa05f value volume-on/off
+$00ffd827 value volume-up
+$00ffc03f value volume-down
+$00ff30cf value brightness
+
+false value done?
+#10 value sleep-seconds
+: sleep ( -- ) true to done? ;
+: set-sleep ( -- ) ['] sleep sleep-seconds #1000 * set-alarm ;
+: cancel-sleep ( -- ) 0 0 set-alarm ;
+
+: both? ( -- flag ) up-switch? down-switch? and ;
+: either? ( -- flag ) up-switch? down-switch? or ;
+
+0 value this-code
+0 value repeat?
+: volume-button ( ir-code pin -- )
+ to switch-gpio to this-code
+ switch? if
+ cancel-sleep
+ led-on
+ #300 ms
+ both? if
+ begin
+ volume-on/off ir-pin ir-packet
+ #1000 ms
+ either? 0= until
+ else
+ begin
+ this-code ir-pin ir-packet
+ #400 ms
+ switch? 0= until
+ then
+ led-off
+ set-sleep
+ then
+;
+: projector-button ( ir-code pin -- )
+ to switch-gpio to this-code
+ switch? if
+ cancel-sleep
+ led-on
+ this-code ir-pin ir-packet
+ begin switch? while #10 ms repeat
+ led-off
+ set-sleep
+ then
+;
+
+: run ( -- )
+ \ wifi-sta-disconnect
+ init-wakeup
+ init-ir
+ init-led
+ init-switches
+ led-on #500 ms led-off
+ false to done?
+ set-sleep
+ begin
+ key? if cancel-sleep quit then
+ projector-on/off projector-switch-pin projector-button
+ volume-up up-switch-pin volume-button
+ volume-down down-switch-pin volume-button
+ #10 ms
+ done? until
+ ." Sleeping" cr
+ blips
+ 4 deep-sleep-option!
+ 0 deep-sleep
+ #1000 ms
+;
+
+\ If you have problems flashing, try:
+\ a) Hitting RST then flashing quickly
+\ b) interacting on the serial
+\ port, then disconnecting TeraTerm, then starting the download.
+
+: app
+\ banner decimal
+\ interrupt? if quit then
+\ ['] load-startup-file catch drop
+ decimal
+ cr ." Remote app. Sleeps after " sleep-seconds . ." seconds." cr
+ ." Type a key to interact" cr
+ \ run
+ quit
+;
+
+" app.dic" save
diff --git a/src/app/remote/extend.c b/src/app/remote/extend.c
new file mode 100644
index 0000000..1a2ec05
--- /dev/null
+++ b/src/app/remote/extend.c
@@ -0,0 +1,860 @@
+// Forth interfaces to platform-specific C routines
+// See "ccalls" below.
+
+#include "forth.h"
+
+extern cell *callback_up;
+
+#include "esp_stdint.h"
+#include "platform.h"
+
+cell deep_sleep(cell us, cell type)
+{
+ // XXX need to save the state in the user area
+ system_deep_sleep_set_option((u_char)type);
+ system_deep_sleep((uint32_t)us);
+}
+
+// For rtc_get_reset_reason()
+// Also has SHA, MD5, base65, cycle counter
+#include "rom.h"
+
+#include "lwip/err.h"
+#include "lwip/pbuf.h"
+
+err_t dns_gethostbyname1(char *hostname, struct ip_addr *ipaddr, xt_t callback, void *arg);
+struct tcp_pcb *tcp_new(void);
+void tcp_arg(struct tcp_pcb *pcb, void* arg);
+struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, uint8_t backlog);
+err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, uint16_t port);
+void tcp_accepted1(struct tcp_pcb *pcb);
+uint16_t tcp_sndbuf1(struct tcp_pcb *pcb);
+err_t tcp_output(struct tcp_pcb *pcb);
+void tcp_recved(struct tcp_pcb *pcb, uint16_t len);
+err_t tcp_close(struct tcp_pcb *pcb);
+void tcp_abort(struct tcp_pcb *pcb);
+uint8_t pbuf_free(struct pbuf *p);
+void tcp_sent_continues(struct tcp_pcb *pcb);
+
+// From lwip.c. We punt on the argument templates to avoid too many include files
+cell tcp_write_sw();
+void tcp_accept1();
+void tcp_connect1();
+void tcp_sent1();
+void tcp_recv1();
+void tcp_poll1();
+void tcp_err1();
+
+
+// Mapping from Nodemcu pin numbers to ESP GPIO numbers
+ // 0 1 2 3 4 5 6 7 8 9 10
+u_char nodemcu_pinmap[] = { 16, 5, 4, 0, 2, 14, 12, 13, 15, 3, 1};
+
+int short_spins, long_spins, ws2812b_gpio_mask;
+void ws2812b_init(cell longspins, cell shortspins, cell gpio) {
+ platform_gpio_mode(gpio, PLATFORM_GPIO_OUTPUT, 0);
+ platform_gpio_write(gpio, 0); // LOW is reset/idle state
+ ws2812b_gpio_mask = 1<<nodemcu_pinmap[gpio];
+ short_spins = shortspins;
+ long_spins = longspins;
+}
+
+void ICACHE_RAM_ATTR ws2812b_write(cell len, cell adr)
+{
+ u_char *p = (u_char *)adr;
+ ets_intr_lock();
+ while(len--) {
+ volatile int first, second;
+ u_char b;
+ b = *p++;
+ int bit;
+ for (bit=0x80; bit; bit >>= 1) {
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, ws2812b_gpio_mask); // HIGH
+ if (b&bit) {
+ first = long_spins;
+ second = short_spins;
+ } else {
+ first = short_spins;
+ second = long_spins;
+ }
+ while (first--) ;
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, ws2812b_gpio_mask); // LOW
+ while (second--) ;
+ }
+ }
+ ets_intr_unlock();
+}
+
+#include "driver/i2c_master.h"
+cell i2c_send(cell byte)
+{
+ i2c_master_writeByte((uint8_t)byte);
+ uint8_t r = i2c_master_getAck();
+ if (r)
+ i2c_master_stop();
+ return r;
+}
+cell i2c_recv(cell nack)
+{
+ uint8_t r = i2c_master_readByte();
+ i2c_master_setAck(nack);
+ if (nack)
+ i2c_master_stop();
+ return r;
+}
+
+// Start + slave address + reg#
+cell i2c_start_write(cell slave, cell reg)
+{
+ i2c_master_start();
+ if (i2c_send(slave<<1))
+ return -1;
+ if (i2c_send(reg))
+ return -1;
+
+ return 0;
+}
+
+cell i2c_start_read(cell slave, cell stop)
+{
+ if (stop)
+ i2c_master_stop();
+ i2c_master_start();
+ return i2c_send((slave<<1) | 1);
+}
+
+cell i2c_rb(cell stop, cell slave, cell reg)
+{
+ if (i2c_start_write(slave, reg))
+ return -1;
+ if (i2c_start_read(slave, stop))
+ return -1;
+ return i2c_recv(1);
+}
+
+cell i2c_wb(cell slave, cell reg, cell value)
+{
+ if (i2c_start_write(slave, reg))
+ return -1;
+ if (i2c_send(value))
+ return -1;
+ i2c_master_stop();
+ return 0;
+}
+
+cell i2c_be_rw(cell stop, cell slave, cell reg)
+{
+ if (i2c_start_write(slave, reg))
+ return -1;
+ if (i2c_start_read(slave, stop))
+ return -1;
+ cell val = i2c_recv(0);
+ val = (val<<8) + i2c_recv(1);
+ return val;
+}
+
+cell i2c_le_rw(cell stop, cell slave, cell reg)
+{
+ if (i2c_start_write(slave, reg))
+ return -1;
+ if (i2c_start_read(slave, stop))
+ return -1;
+ cell val = i2c_recv(0);
+ val += i2c_recv(1)<<8;
+ return val;
+}
+
+cell i2c_be_ww(cell slave, cell reg, cell value)
+{
+ if (i2c_start_write(slave, reg))
+ return -1;
+ if (i2c_send(value>>8))
+ return -1;
+ if (i2c_send(value&0xff))
+ return -1;
+ i2c_master_stop();
+ return 0;
+}
+
+cell i2c_le_ww(cell slave, cell reg, cell value)
+{
+ if (i2c_start_write(slave, reg))
+ return -1;
+ if (i2c_send(value&0xff))
+ return -1;
+ if (i2c_send(value>>8))
+ return -1;
+ i2c_master_stop();
+ return 0;
+}
+
+extern void ets_timer_arm_new(os_timer_t* t, uint32_t milliseconds, uint32_t repeat_flag, uint32_t isMstimer);
+extern void ets_timer_disarm(os_timer_t* t);
+extern void ets_timer_setfn(os_timer_t* t, os_timer_func_t *f, void *arg);
+extern void ets_delay_us(uint32_t us);
+
+static os_timer_t delay_timer;
+
+static void delay_callback(void *arg)
+{
+ inner_interpreter(callback_up);
+}
+
+static void start_ms(cell ms)
+{
+ ets_timer_setfn(&delay_timer, delay_callback, NULL);
+ ets_timer_arm_new(&delay_timer, ms, 0, 1);
+}
+
+#define ALARM_DATA_CELLS 100
+#define ALARM_RETURN_CELLS 50
+cell alarm_data_stack[ALARM_DATA_CELLS];
+cell alarm_return_stack[ALARM_RETURN_CELLS];
+struct stacks alarm_stacks_save;
+struct stacks alarm_stacks = {
+ (cell)&alarm_data_stack[ALARM_DATA_CELLS-2],
+ (cell)&alarm_data_stack[ALARM_DATA_CELLS-2],
+ (cell)&alarm_return_stack[ALARM_RETURN_CELLS],
+ (cell)&alarm_return_stack[ALARM_RETURN_CELLS]
+};
+
+static os_timer_t alarm_timer;
+
+static void alarm_callback(void *arg)
+{
+ switch_stacks(&alarm_stacks_save, &alarm_stacks, callback_up);
+ execute_xt((xt_t)arg, callback_up);
+ switch_stacks(NULL, &alarm_stacks_save, callback_up);
+}
+
+static void alarm(cell ms, cell xt)
+{
+ if (xt && ms) {
+ ets_timer_setfn(&alarm_timer, alarm_callback, (void *)xt);
+ ets_timer_arm_new(&alarm_timer, ms, 0, 1);
+ } else {
+ ets_timer_disarm(&alarm_timer);
+ }
+}
+
+static void repeat_alarm(cell ms, cell xt)
+{
+ if (xt && ms) {
+ ets_timer_setfn(&alarm_timer, alarm_callback, (void *)xt);
+ ets_timer_arm_new(&alarm_timer, ms, 1, 1);
+ } else {
+ ets_timer_disarm(&alarm_timer);
+ }
+}
+
+#if 0 // Doesn't work; counts milliseconds despite the 0 final argument
+// Actually, it does work after you call "reinit-timer"
+static void start_us(cell us)
+{
+ ets_timer_setfn(&delay_timer, delay_callback, NULL);
+ ets_timer_arm_new(&delay_timer, us, 0, 0);
+}
+#endif
+
+typedef struct {
+ os_timer_t os_timer;
+ xt_t cb_xt;
+ uint32_t interval;
+ uint32_t isms;
+ uint32_t repeat;
+} timer_t;
+
+static void timer_callback(void *arg)
+{
+ timer_t *tp = (timer_t *)arg;
+
+ if (!tp->cb_xt)
+ return;
+
+ cell *up = callback_up;
+ execute_xt((xt_t)tp->cb_xt, up);
+}
+
+timer_t *new_timer(xt_t cb_xt)
+{
+ timer_t *tp = (timer_t *)pvPortZalloc(sizeof(timer_t), "", 0);
+ ets_timer_setfn(&(tp->os_timer), timer_callback, (void *)tp);
+ tp->cb_xt = cb_xt;
+ return tp;
+}
+
+void rearm_timer(timer_t *tp)
+{
+ ets_timer_arm_new(&(tp->os_timer), tp->interval, tp->repeat, tp->isms);
+}
+
+// This argument order is better for Forth
+void arm_timer(timer_t *tp, uint32_t repeat, uint32_t isms, uint32_t interval)
+{
+ tp->interval = interval;
+ tp->isms = isms;
+ tp->repeat = repeat;
+ rearm_timer(tp);
+}
+
+void disarm_timer(timer_t *tp)
+{
+ ets_timer_disarm(&(tp->os_timer));
+}
+
+static os_timer_t step_timer;
+int sensor_pin;
+int stepper_pin;
+int current_us;
+int target_us;
+int remaining_steps = -1;
+
+void do_step(void *foo)
+{
+ if (remaining_steps >= 0) {
+ platform_gpio_write(stepper_pin, 0);
+ ets_delay_us(5);
+ platform_gpio_write(stepper_pin, 1);
+ if (remaining_steps == 0) {
+ if (sensor_pin < 0 || platform_gpio_read(sensor_pin)) {
+ ets_timer_disarm(&step_timer);
+ remaining_steps = -1;
+ }
+ } else {
+ if (current_us > target_us) {
+ // Ramping up speed
+ if (--current_us == target_us) {
+ // We have reached the target so auto-repeat the timer
+ ets_timer_arm_new(&step_timer, target_us, 1, 0);
+ } else {
+ // Still ramping; single-shot timer at new rate
+ ets_timer_arm_new(&step_timer, current_us, 0, 0);
+ }
+ }
+ --remaining_steps;
+ }
+ }
+}
+
+void start_stepper(int sensor, int stepper, int us_slow, int us_fast, int steps)
+{
+ current_us = us_slow;
+ target_us = us_fast;
+ sensor_pin = sensor;
+ stepper_pin = stepper;
+ remaining_steps = steps;
+ ets_timer_setfn(&step_timer, do_step, NULL);
+ if (current_us == target_us) {
+ // No speed ramp, set timer to auto-repeat
+ ets_timer_arm_new(&step_timer, target_us, 1, 0);
+ } else {
+ // Speed ramp, set single-shot timer to first speed
+ ets_timer_arm_new(&step_timer, current_us, 0, 0);
+ }
+}
+
+cell remsteps(void)
+{
+ return remaining_steps;
+}
+
+
+static os_timer_t pwm_timer;
+int pwm_pin;
+int pwm_on_us;
+int pwm_off_us;
+void do_pwm_off(void *);
+void do_pwm_on(void *foo)
+{
+ platform_gpio_write(pwm_pin, 1);
+ if (pwm_on_us) {
+ ets_timer_setfn(&pwm_timer, do_pwm_off, NULL);
+ ets_timer_arm_new(&pwm_timer, pwm_on_us, 0, 0);
+ }
+}
+void do_pwm_off(void *foo)
+{
+ platform_gpio_write(pwm_pin, 0);
+ if (pwm_off_us) {
+ ets_timer_setfn(&pwm_timer, do_pwm_on, NULL);
+ ets_timer_arm_new(&pwm_timer, pwm_off_us, 0, 0);
+ }
+}
+void set_pwm(int pin, int on_us, int off_us) {
+ pwm_pin = pin;
+ pwm_on_us = on_us;
+ pwm_off_us = off_us;
+ ets_timer_disarm(&pwm_timer);
+ if (pwm_on_us) {
+ do_pwm_on(NULL);
+ }
+}
+void ICACHE_RAM_ATTR ir_cycles(int gpio, int cycles)
+{
+ int mask = 1<<nodemcu_pinmap[gpio];
+ while (cycles--) {
+ ets_delay_us(13);
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, mask); // HIGH
+ ets_delay_us(12);
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, mask); // LOW
+ }
+}
+
+void ICACHE_RAM_ATTR ir_packet(int gpio, uint32_t data)
+{
+ ets_intr_lock();
+ ir_cycles(gpio, 348); // Start pulse
+ ets_delay_us(4500); // End of start sequence
+ int i;
+ for (i = 31; i >= 0; i--) {
+ ir_cycles(gpio, 23);
+ ets_delay_us(data & (1<<i) ? 1600 : 640);
+ }
+ ir_cycles(gpio, 23); // Stop bit
+ ets_intr_unlock();
+}
+
+xt_t gpio_callback_xt[NUM_GPIO];
+
+#include "pin_map.h"
+
+static void platform_gpio_intr_dispatcher(void *arg) {
+ void (*cb)(unsigned, unsigned) = arg;
+ uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
+ uint8_t i, level;
+ for (i = 0; i < GPIO_PIN_NUM; i++) {
+ if (pin_int_type[i] && (gpio_status & BIT(pin_num[i])) ) {
+ //disable interrupt
+ gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[i]), GPIO_PIN_INTR_DISABLE);
+ //clear interrupt status
+ GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(pin_num[i]));
+ level = 0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(pin_num[i]));
+ if(cb){
+ cb(i, level);
+ }
+ gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[i]), pin_int_type[i]);
+ }
+ }
+}
+
+void gpio_callback(unsigned pin, unsigned level)
+{
+ if (!gpio_callback_xt[pin])
+ return;
+ cell *up = callback_up;
+ // We assume that a GPIO callback cannot interrupt an alarm
+ // callback, nor can one GPIO callback interrupt another.
+ // If that is incorrect, everything would need separate stacks
+ switch_stacks(&alarm_stacks_save, &alarm_stacks, up);
+ spush(level, up);
+ execute_xt((xt_t)gpio_callback_xt[pin], up);
+ switch_stacks(NULL, &alarm_stacks_save, up);
+}
+
+void gpio_set_callback(unsigned pin, xt_t cb_xt)
+{
+ if (pin >= NUM_GPIO)
+ return;
+ gpio_callback_xt[pin] = cb_xt;
+ ETS_GPIO_INTR_ATTACH(platform_gpio_intr_dispatcher, (void *)gpio_callback);
+}
+
+unsigned last_value;
+unsigned got_value;
+unsigned value;
+unsigned ir_pin;
+unsigned last_edge;
+unsigned delta;
+unsigned state;
+enum {
+ ERROR=-4,
+ IDLE=-3,
+ START0=-2,
+ START1=-1,
+ SEND=64,
+ REPEAT0=66,
+ REPEAT1=67,
+ REPEAT2=68,
+ REPEAT3=69
+};
+
+unsigned v_delta() { return delta; }
+unsigned v_last_edge() { return last_edge; }
+unsigned v_value() { return value; }
+unsigned v_state() { return state; }
+
+void notify()
+{
+ got_value = 1;
+ last_value = value;
+}
+
+cell read_value()
+{
+ if (got_value) {
+ got_value = 0;
+ return last_value;
+ }
+ return -1;
+}
+
+void ir_decode(unsigned pin, unsigned level)
+{
+ unsigned bit;
+ unsigned this_edge;
+ if (pin != ir_pin)
+ return;
+ delta = system_get_time() - last_edge;
+ last_edge += delta;
+ if (level) { // rising edge
+ if (delta < 500) {
+ state = ERROR;
+ } else if (delta < 700) {
+ if (state == REPEAT2) {
+ state = IDLE;
+ } else {
+ state++;
+ if (state == SEND) {
+ notify();
+ }
+ }
+ } else if (delta < 8500) {
+ state = ERROR;
+ } else if (delta < 9500) {
+ state = state == REPEAT0 ? REPEAT1 : START0;
+ } else {
+ state = ERROR;
+ }
+ } else { // falling edge
+ if (delta < 500) {
+ state = ERROR;
+ } else if (delta < 700) {
+ state++;
+ bit = 0;
+ } else if (delta < 1700) {
+ state = ERROR;
+ } else if (delta < 1900) {
+ state++;
+ bit = 1;
+ } else if (delta < 2400) {
+ state = state == REPEAT1 ? REPEAT2 : ERROR;
+ } else if (delta < 4400) {
+ state = ERROR;
+ } else if (delta < 4700) {
+ value = 0;
+ state = state == START0 ? START1 : ERROR;
+ } else if (delta < 38000) {
+ state = ERROR;
+ } else if (delta < 41000) {
+ state = REPEAT0;
+ } else {
+ state = ERROR;
+ }
+ if (state > 0 && state < 64) {
+ if ((state & 1) == 0) {
+ state = ERROR;
+ } else {
+ value |= bit << (state >> 1);
+ }
+ }
+ }
+}
+
+void ir_attach(unsigned pin)
+{
+ if (pin >= NUM_GPIO)
+ return;
+ ir_pin = pin;
+ platform_gpio_mode(pin, PLATFORM_GPIO_INT, 0);
+ ETS_GPIO_INTR_ATTACH(platform_gpio_intr_dispatcher, (void *)ir_decode);
+ platform_gpio_intr_init(pin, 3); // anyedge
+}
+
+void i2c_setup(cell sda, cell scl)
+{
+ platform_i2c_setup(0, sda, scl, 100000);
+}
+
+
+// Defined in fileio.c
+void myspiffs_format(void);
+void rename_file(char *new, char *old);
+cell fs_avail(void);
+void delete_file(char *path);
+void *next_file(void);
+void *first_file(void);
+cell dirent_size(void *);
+cell dirent_name(void *);
+
+// extern void SPIRead(void);
+extern void raw_putchar(unsigned char c);
+
+#include "driver/onewire.h"
+
+uint8_t owpin;
+uint8_t owpower;
+void ow_init(uint8_t pin, int power) { owpin = pin; owpower = power; onewire_init(owpin); };
+uint8_t ow_reset() { return onewire_reset(owpin); };
+void ow_select(const uint8_t rom[8]) { onewire_select(owpin, rom); };
+void ow_skip() { onewire_skip(owpin); };
+void ow_write(uint8_t v) { onewire_write(owpin, v, owpower); };
+void ow_write_bytes(const uint8_t *buf, uint16_t count) { onewire_write_bytes(owpin, buf, count, owpower); };
+uint8_t ow_read() { return onewire_read(owpin); };
+void ow_read_bytes(uint8_t *buf, uint16_t count) { onewire_read_bytes(owpin, buf, count); };
+void ow_depower() { onewire_depower(owpin); };
+void ow_reset_search() { onewire_reset_search(owpin); };
+void ow_target_search(uint8_t family_code) { onewire_target_search(owpin, family_code); };
+uint8_t ow_search(uint8_t *newAddr) { onewire_search(owpin, newAddr); };
+
+cell version_adr(void)
+{
+ extern char version[];
+ return (cell)version;
+}
+
+cell build_date_adr(void)
+{
+ extern char build_date[];
+ return (cell)build_date;
+}
+
+void spi_open();
+void spi_close();
+void spi_begin();
+void spi_end();
+void spi_transfer();
+void spi_bits_in();
+
+cell ((* const ccalls[])()) = {
+ C(build_date_adr) //c 'build-date { -- a.value }
+ C(version_adr) //c 'version { -- a.value }
+ C(raw_putchar) //c m-emit { i.char -- }
+
+ C(myspiffs_format) //c fs-format { -- }
+ C(rename_file) //c rename-file { $.old $.new -- }
+ C(delete_file) //c delete-file { $.name -- }
+ C(fs_avail) //c fs-avail { -- i.bytes }
+ C(first_file) //c first-file { -- a.dirp }
+ C(next_file) //c next-file { -- a.dirp' }
+ C(dirent_size) //c file-bytes { a.dirp -- i.size }
+ C(dirent_name) //c file-name { a.dirp -- a.name }
+
+ C(SPIRead) //c spi-read { i.len a.buf i.id -- }
+
+ C(ow_init) //c ow-init { i.power i.id -- }
+ C(ow_reset) //c ow-reset { -- i.present? }
+ C(ow_select) //c ow-select { a.romp -- }
+ C(ow_skip) //c ow-skip { -- }
+ C(ow_write) //c ow-b! { i.byte -- }
+ C(ow_write_bytes) //c ow-write { i.len a.adr -- }
+ C(ow_read) //c ow-b@ { -- }
+ C(ow_read_bytes) //c ow-read { i.len a.adr -- }
+ C(ow_depower) //c ow-depower { -- }
+ C(ow_reset_search) //c ow-reset-search { -- }
+ C(ow_target_search) //c ow-target-search { i.family -- }
+ C(ow_search) //c ow-search { a.newaddr -- i.ok? }
+ C(onewire_crc8) //c ow-crc8 { i.len a.adr -- i.crc }
+ C(onewire_check_crc16)//c ow-check-crc16 { i.crc a.invcrc i.len a.input -- i.ok? }
+ C(onewire_crc16) //c ow-crc16 { i.crc i.len a.adr -- i.crc }
+
+ C(i2c_setup) //c i2c-setup { i.scl i.sda -- }
+ C(i2c_master_start) //c i2c-start { -- }
+ C(i2c_master_stop) //c i2c-stop { -- }
+ C(i2c_send) //c i2c-byte! { i.byte -- acked? }
+ C(i2c_recv) //c i2c-byte@ { i.nack? -- i.byte }
+ C(i2c_start_write) //c i2c-start-write { i.reg i.slave -- i.err? }
+ C(i2c_start_read) //c i2c-start-read { i.stop? i.slave -- i.err? }
+ C(i2c_rb) //c i2c-b@ { i.reg i.slave i.stop -- b }
+ C(i2c_wb) //c i2c-b! { i.value i.reg i.slave -- error? }
+ C(i2c_be_rw) //c i2c-be-w@ { i.reg i.slave i.stop -- w }
+ C(i2c_le_rw) //c i2c-le-w@ { i.reg i.slave i.stop -- w }
+ C(i2c_be_ww) //c i2c-be-w! { i.value i.reg i.slave -- error? }
+ C(i2c_le_ww) //c i2c-le-w! { i.value i.reg i.slave -- error? }
+
+ C(platform_gpio_mode) //c gpio-mode { i.pull i.mode i.pin -- }
+ C(platform_gpio_write) //c gpio-pin! { i.level i.pin -- }
+ C(platform_gpio_read) //c gpio-pin@ { i.pin -- i.level }
+ C(platform_gpio_intr_init)//c gpio-enable-interrupt { i.type i.pin -- }
+ C(gpio_set_callback) //c gpio-callback! { i.cb_xt i.pin -- }
+
+ C(system_get_rst_info) //c reset-info { -- a.rst_info }
+ C(system_restore) //c restore { -- }
+ C(system_restart) //c restart { -- }
+ C(system_deep_sleep_set_option) //c deep-sleep-option! { i.option -- }
+ C(system_deep_sleep) //c deep-sleep { i.us -- }
+ C(system_timer_reinit) //c reinit-timer { -- }
+ C(system_get_time) //c timer@ { -- i.counter }
+ C(system_os_post) //c post-event { i.param i.sig i.prio -- i.stat }
+ // X(system_print_meminfo) //x .meminfo { -- }
+ C(system_get_free_heap_size) //c heap-size { -- i.size }
+ // X(system_get_os_print) //x system_get_os_print { -- i.on/off }
+ C(system_set_os_print) //c set-printf { i.on/off -- }
+ C(system_mktime) //c mktime { i.sec i.min i.hr i.day i.mon i.yr -- i.time }
+ C(system_get_chip_id) //c chip-id@ { -- i.id }
+ C(system_rtc_clock_cali_proc) //c rtc-clock-cal { -- i.val }
+ C(system_get_rtc_time) //c rtc-time@ { -- i.time }
+
+ C(system_rtc_mem_read) //c rtc-mem-read { i.len a.buf i.offset -- i.stat }
+ C(system_rtc_mem_write) //c rtc-mem-write { i.len a.buf i.offset -- i.stat }
+
+ C(system_uart_swap) //c system_uart_swap { -- }
+ C(system_uart_de_swap) //c system_uart_de_swap { -- }
+
+ C(system_adc_read) //c adc@ { -- n }
+ C(system_get_vdd33) //c vdd33@ { -- n }
+
+ C(system_get_sdk_version) //c sdk-version$ { -- a.vers }
+ C(system_get_boot_version) //c boot-version@ { -- i.version }
+ C(system_get_userbin_addr) //c userbin-addr@ { -- i.addr }
+ C(system_get_boot_mode) //c boot-mode@ { -- i.mode }
+ C(system_restart_enhance) //c restart-enhance { i.bin_type i.bin_addr -- i.stat }
+ C(system_update_cpu_freq) //c cpu-freq! { i.freq -- i.stat }
+ C(system_get_cpu_freq) //c cpu-freq@ { -- i.mhz }
+ C(system_get_flash_size_map) //c flash-size-map@ { -- i.enum }
+ C(system_phy_set_max_tpw) //c phy-max-tpw! { i.max -- }
+ C(system_phy_set_tpw_via_vdd33) //c phy-tpw-via-vdd33! { i.vdd33 -- }
+ C(system_phy_set_rfoption) //c phy-rfoption! { i.option -- }
+ C(system_phy_set_powerup_option) //c phy-powerup-option! { i. option -- }
+ C(system_param_save_with_protect) //c save-param-with-protect { i.len a.param i.start_sec -- i.stat }
+ C(system_param_load) //c load-param { i.len a.param i.offset -- i.stat }
+ C(system_soft_wdt_stop) //c soft-wdt-stop { -- }
+ C(system_soft_wdt_restart) //c soft-wdt-restart { -- }
+ C(system_soft_wdt_feed) //c soft-wdt-feed { -- }
+ C(system_show_malloc) //c show-malloc { -- }
+
+ C(wifi_set_phy_mode) //c wifi-phymode! { i.mode -- }
+ C(wifi_get_phy_mode) //c wifi-phymode@ { -- i.mode }
+ C(wifi_set_sleep_type) //c wifi-sleeptype! { i.type -- }
+ C(wifi_get_sleep_type) //c wifi-sleeptype@ { -- i.type }
+ C(wifi_set_opmode) //c wifi-opmode! { i.mode -- }
+ C(wifi_get_opmode) //c wifi-opmode@ { -- i.mode }
+ C(wifi_set_broadcast_if) //c wifi-broadcast-if! { i.mode -- i.stat }
+ C(wifi_get_broadcast_if) //c wifi-broadcast-if@ { -- i.mode }
+
+ C(wifi_station_get_config) //c wifi-sta-config@ { a.buf -- i.stat }
+ C(wifi_station_set_config) //c wifi-sta-config! { a.buf -- i.stat }
+
+ C(wifi_station_connect) //c wifi-sta-connect { -- i.stat }
+ C(wifi_station_disconnect) //c wifi-sta-disconnect { -- i.stat }
+
+ C(wifi_station_get_rssi) //c wifi-sta-get-rssi { -- i.rssi }
+
+ C(wifi_station_scan) //c wifi-sta-scan { i.done-cb a.config -- i.stat }
+ C(wifi_station_get_auto_connect) //c wifi-sta-auto-connect@ { -- i.on? }
+ C(wifi_station_set_auto_connect) //c wifi-sta-auto-connect! { i.on? -- i.stat }
+ C(wifi_station_set_reconnect_policy) //c wifi-sta-reconnect! { i.on? -- i.stat }
+ C(wifi_station_get_connect_status) //c wifi-sta-connect@ { -- i.status }
+ C(wifi_station_get_current_ap_id) //c wifi-sta-ap-id@ { -- i.id }
+ C(wifi_station_ap_change) //c wifi-sta-ap-id! { i.id -- i.stat }
+ C(wifi_station_ap_number_set) //c wifi-sta-ap-number! { i.ap# -- i.stat }
+ C(wifi_station_get_ap_info) //c wifi-sta-ap-info@ { a.buf -- i.n }
+ C(wifi_station_dhcpc_start) //c wifi-sta-dhcpc-start { -- i.stat }
+ C(wifi_station_dhcpc_stop) //c wifi-sta-dhcpc-stop { -- i.stat }
+ C(wifi_station_dhcpc_status) //c wifi-sta-dhcpc-status { -- i.dhcpstat }
+ C(wifi_station_dhcpc_set_maxtry) //c wifi-sta-dhcpc-retry! { i.#retries -- i.stat }
+ C(wifi_station_get_hostname) //c wifi-sta-hostname@ { -- $.hostname }
+ C(wifi_station_set_hostname) //c wifi-sta-hostname! { $.hostname -- i.stat }
+ C(wifi_softap_get_config) //c wifi-ap-config@ { a.config -- i.stat }
+ C(wifi_softap_set_config) //c wifi-ap-config! { a.config -- i.stat }
+ C(wifi_softap_set_config_current) //c wifi-ap-config-current! { a.config -- i.stat }
+ C(wifi_softap_get_station_num) //c wifi-ap-station-num@ { -- i.# }
+ C(wifi_softap_get_station_info) //c wifi-ap-station-info@ { -- a.info }
+ C(wifi_softap_free_station_info) //c wifi-ap-free-station-info { -- }
+ C(wifi_softap_dhcps_start) //c wifi-ap-dhcps-start { -- i.stat }
+ C(wifi_softap_dhcps_stop) //c wifi-ap-dhcps-stop { -- i.stat }
+ C(wifi_softap_set_dhcps_lease) //c wifi-ap-dhcps-lease! { a.lease -- i.stat }
+ C(wifi_softap_get_dhcps_lease) //c wifi-ap-dhcps-lease@ { a.lease -- i.stat }
+ C(wifi_softap_get_dhcps_lease_time) //c wifi-ap-dhcps-lease-time@ { -- i.time }
+ C(wifi_softap_set_dhcps_lease_time) //c wifi-ap-dhcps-lease-time! { i.minutes -- i.stat }
+ C(wifi_softap_reset_dhcps_lease_time) //c wifi-ap-reset-dhcps-lease-time { -- i.stat }
+ C(wifi_softap_dhcps_status) //c wifi-ap-dhcps-status { -- i.dhcpstat }
+ C(wifi_softap_set_dhcps_offer_option) //c wifi-ap-dhcps-offer-option! { a.optarg i.level -- i.stat }
+ C(wifi_get_ip_info) //c wifi-ip-info@ { a.ip_info i.if# -- i.stat }
+ C(wifi_set_ip_info) //c wifi-ip-info! { a.ip_info i.if# -- i.stat }
+ C(wifi_get_macaddr) //c wifi-macaddr@ { a.mac i.if# -- i.stat }
+ C(wifi_set_macaddr) //c wifi-macaddr! { a.mac i.if# -- i.stat }
+ C(wifi_get_channel) //c wifi-channel@ { -- i.ch# }
+ C(wifi_set_channel) //c wifi-channel! { i.channel -- i.stat }
+ C(wifi_status_led_install) //c wifi-status-led-install { i.func i.gpioname i.gpioid -- }
+ C(wifi_status_led_uninstall) //c wifi-status-led-uninstall { -- }
+ C(wifi_promiscuous_enable) //c wifi-promiscuous-enable { i.promiscuous) -- }
+ C(wifi_set_promiscuous_rx_cb) //c wifi-promiscuous-rx-cb! { i.cb_xt -- }
+ C(wifi_promiscuous_set_mac) //c wifi-promiscuous-mac! { a.mac -- }
+ C(wifi_fpm_open) //c wifi-fpm-open { -- }
+ C(wifi_fpm_close) //c wifi-fpm-close { -- }
+ C(wifi_fpm_do_wakeup) //c wifi-fpm-do-wakeup { -- }
+ C(wifi_fpm_do_sleep) //c wifi-fpm-do-sleep { i.us -- i.res }
+ C(wifi_fpm_set_sleep_type) //c wifi-fpm-sleep-type! { i.sleeptype -- }
+ C(wifi_fpm_get_sleep_type) //c wifi-fpm-sleep-type@ { -- i.sleeptype }
+ C(wifi_set_event_handler_cb) //c wifi-set-event-handler-cb { i.cbxt -- }
+
+ C(flash_rom_get_mode) //c flash-mode { -- i.mode }
+ C(flash_rom_get_speed) //c flash-speed { -- i.speed }
+ C(flash_rom_get_size_byte)//c flash-size { -- i.size }
+
+ C(new_timer) //c new-timer { i.cb_xt -- a.timer }
+ C(arm_timer) //c arm-timer { i.interval i.isms i.repeat a.timer -- }
+ C(rearm_timer) //c rearm-timer { a.timer -- }
+ C(disarm_timer) //c disarm-timer { a.timer -- }
+
+ C(start_ms) //c start-ms { i.ms -- }
+ C(ets_delay_us) //c us { i.usecs -- }
+
+ C(alarm) //c set-alarm { i.xt i.ms -- }
+ C(repeat_alarm) //c repeat-alarm { i.xt i.ms -- }
+
+ C(spi_flash_get_id) //c flash-id { -- i.id }
+ C(spi_flash_erase_sector) //c flash-erase { i.sector -- i.result }
+ C(spi_flash_write) //c flash-write { i.len a.adr i.offset -- i.result }
+ C(spi_flash_read) //c flash-read { i.len a.adr i.offset -- i.result }
+
+ C(rtc_get_reset_reason) //c reset-reason { -- i.reason }
+ C(xthal_get_ccount) //c xthal_get_ccount { -- i.count }
+
+ C(dns_gethostbyname1) //c dns-gethostbyname { a.arg i.xt a.ipaddr a.hostname -- i.stat }
+
+ C(tcp_write_sw) //c tcp-write { a.adr i.len a.pcb -- i.stat }
+ C(tcp_new) //c tcp-new { -- a.pcb }
+ C(tcp_arg) //c tcp-arg { a.arg a.pcb -- }
+ C(tcp_bind) //c tcp-bind { i.port a.ipaddr a.pcb -- i.stat }
+ C(tcp_listen_with_backlog)//c tcp-listen-backlog { i.backlog a.pcb1 -- a.pcb2 }
+ C(tcp_accept1) //c tcp-accept { i.xt a.pcb -- }
+ C(tcp_accepted1) //c tcp-accepted { a.pcb -- }
+ C(tcp_connect1) //c tcp-connect { i.xt i.port a.ipaddr a.pcb -- i.stat }
+ C(tcp_sent1) //c tcp-sent { i.xt a.pcb -- }
+ C(tcp_recv1) //c tcp-recv { i.xt a.pcb -- }
+ C(tcp_poll1) //c tcp-poll { i.interval i.xt a.pcb -- }
+ C(tcp_err1) //c tcp-err { i.xt a.pcb -- }
+ C(tcp_sndbuf1) //c tcp-sendbuf { a.pcb -- i.#bytes }
+ C(tcp_output) //c tcp-output { a.pcb -- i.stat }
+ C(tcp_recved) //c tcp-recved { i.len a.pcb -- }
+ C(tcp_close) //c tcp-close { a.pcb -- i.stat }
+ C(tcp_abort) //c tcp-abort { a.pcb -- }
+ C(pbuf_free) //c pbuf-free { a.pbuf -- i.#freed }
+ C(tcp_sent_continues) //c tcp-sent-continues { a.pcb -- }
+
+ C(spi_open) //c spi-open { i.datamode i.msb i.clock i.csgpio -- }
+ C(spi_close) //c spi-close { -- }
+ C(spi_begin) //c spi{ { -- }
+ C(spi_end) //c }spi { -- }
+ C(spi_transfer) //c spi-transfer { a.outp a.inp i.size -- }
+ C(spi_bits_in) //c spi-bits@ { i.#bits -- i.bits }
+
+ C(ws2812b_init) //c init-ws2812b { i.gpio# i.short_spins i.long_spins -- }
+ C(ws2812b_write) //c write-ws2812b { a.adr i.len -- }
+
+ C(start_stepper) //c start-stepper { i.steps i.usfast i.usslow i.step-pin i.sensor-pin -- }
+ C(remsteps) //c steps-left { -- i.steps }
+
+ C(set_pwm) //c set-pwm { i.off_us i.on_us i.pin -- }
+
+ C(ir_cycles) //c ir-cycles { i.cycles i.pin -- }
+ C(ir_packet) //c ir-packet { i.data i.pin -- }
+
+ C(v_delta) //c ir-delta { -- i.ticks }
+ C(v_last_edge) //c ir-last-edge { -- i.ticks }
+ C(v_value) //c ir-value { -- i.value }
+ C(v_state) //c ir-state { -- i.value }
+ C(ir_attach) //c ir-attach { i.pin -- }
+ C(read_value) //c ir-read { -- value | -1 }
+};