mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
merge upstream from origin/master
This commit is contained in:
commit
07a5717611
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
*~
|
||||
*.tgz
|
||||
*.d
|
||||
*.o
|
||||
*.elf
|
||||
/*.hex
|
||||
@ -30,3 +31,5 @@ xtensa-lx106-elf
|
||||
*.c#
|
||||
/function_keywords.js
|
||||
/functions.html
|
||||
targetlibs/nrf5x/examples
|
||||
/.vscode
|
||||
|
||||
@ -39,7 +39,7 @@ compiler:
|
||||
|
||||
env:
|
||||
global:
|
||||
#- RELEASE=1
|
||||
- RELEASE=1
|
||||
- TRAVIS=1
|
||||
- V=0
|
||||
- ESP8266_SDK_ROOT=$TRAVIS_BUILD_DIR/esp_iot_sdk_v2.0.0.p1
|
||||
@ -63,6 +63,7 @@ env:
|
||||
- LCTECH_STM32F103RBT6=1
|
||||
- LINUX_BUILD=1
|
||||
- EFM32GGSTK=1
|
||||
- NUCLEOL476RG=1
|
||||
script: make
|
||||
|
||||
notifications:
|
||||
|
||||
@ -6,6 +6,14 @@
|
||||
Puck.js: Allow Puck.IR to take pins for external IR LED (fix #927)
|
||||
nRF52: Allow arbitrary NFC data to be specified (fix #1021)
|
||||
nRF5x: Allow multiple advertising packets to be set at once with NRF.setAdvertising
|
||||
nRF52: Add 'properties' object to BluetoothRemoteGATTCharacteristic
|
||||
nRF52: Perform write without response if that is what is required
|
||||
Pico/WiFi: Allow USB HID to work on Windows (from @nailxx)
|
||||
Allow Puck.js/nRF52 devices to drive Neopixel/WS281x/APA10x LEDs with E.neopixelWrite (fix #1023)
|
||||
Fix crash in JSON.stringify for zero-length typed arrays
|
||||
Fix precedence of 'void' keyword (fix #1079)
|
||||
nRF52: Add BluetoothRemoteGATTCharacteristic.startNotifications (fix #959)
|
||||
nRF52: Added BluetoothDevice.gattserverdisconnected event
|
||||
|
||||
1v91 : Fix recent regression if no Boot Code defined at startup
|
||||
Fix handling of return of rejected promise within a promise
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
FROM ubuntu:14.04
|
||||
|
||||
RUN apt-get update && apt-get install -y software-properties-common && apt-get update \
|
||||
&& add-apt-repository ppa:terry.guo/gcc-arm-embedded \
|
||||
&& add-apt-repository ppa:team-gcc-arm-embedded/ppa \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y git gcc-arm-none-eabi build-essential python
|
||||
&& apt-get install -y git gcc-arm-embedded build-essential python
|
||||
|
||||
RUN git clone https://github.com/espruino/Espruino espruino
|
||||
WORKDIR /espruino
|
||||
|
||||
203
Makefile
Executable file → Normal file
203
Makefile
Executable file → Normal file
@ -46,6 +46,7 @@
|
||||
# MINISTM32_ANGLED_VE=1
|
||||
# MINISTM32_ANGLED_VG=1
|
||||
# ESP8266_BOARD=1 # ESP8266
|
||||
# ESP32=1 # ESP32
|
||||
# EFM32GGSTK=1 # Currently only works with DEBUG=1
|
||||
# EMW3165=1 # MXCHIP EMW3165: STM32F411CE, BCM43362, 512KB flash 128KB RAM
|
||||
# Or nothing for standard linux compile
|
||||
@ -76,6 +77,7 @@
|
||||
# VARIABLES=1700 # Sets number of variables for project defined firmware. This parameter can be dangerous, be careful before changing.
|
||||
# # used in build_platform_config.py
|
||||
# NO_COMPILE=1 # skips compiling and linking part, used to echo WRAPPERSOURCES only
|
||||
# RTOS # adds RTOS functions, available only for ESP32 (yet)
|
||||
|
||||
ifndef GENDIR
|
||||
GENDIR=$(shell pwd)/gen
|
||||
@ -564,6 +566,17 @@ USE_FILESYSTEM=1
|
||||
USE_GRAPHICS=1
|
||||
USE_NET=1
|
||||
|
||||
else ifdef ESP32
|
||||
BOARD=ESP32
|
||||
EMBEDDED=1
|
||||
USE_NET=1
|
||||
#USE_HASHLIB=1
|
||||
USE_GRAPHICS=1
|
||||
USE_CRYPTO=1
|
||||
USE_TLS=1
|
||||
USE_TELNET=1
|
||||
DEFINES+=-DESP_PLATFORM -DESP32=1
|
||||
OPTIMIZEFLAGS+=-Og
|
||||
|
||||
else ifdef ESP8266_BOARD
|
||||
RELEASE=1
|
||||
@ -758,6 +771,8 @@ ifdef WIZNET
|
||||
USE_WIZNET=1
|
||||
else ifeq ($(FAMILY),ESP8266)
|
||||
USE_ESP8266=1
|
||||
else ifeq ($(FAMILY),ESP32)
|
||||
USE_ESP32=1
|
||||
else ifdef EMW3165
|
||||
USE_WICED=1
|
||||
else
|
||||
@ -1012,6 +1027,26 @@ ifdef USE_NET
|
||||
targetlibs/wiced/wwd/internal/bus_protocols/SDIO/wwd_bus_protocol.c
|
||||
endif
|
||||
|
||||
ifdef USE_ESP32
|
||||
DEFINES += -DUSE_ESP32
|
||||
WRAPPERSOURCES += libs/network/esp32/jswrap_esp32_network.c \
|
||||
targets/esp32/jswrap_esp32.c
|
||||
INCLUDE += -I$(ROOT)/libs/network/esp32
|
||||
SOURCES += libs/network/esp32/network_esp32.c \
|
||||
targets/esp32/i2c.c \
|
||||
targets/esp32/spi.c \
|
||||
targets/esp32/jshardwareUart.c \
|
||||
targets/esp32/jshardwareAnalog.c \
|
||||
targets/esp32/jshardwarePWM.c \
|
||||
targets/esp32/rtosutil.c \
|
||||
targets/esp32/jshardwareTimer.c \
|
||||
targets/esp32/jshardwarePulse.c
|
||||
ifdef RTOS
|
||||
DEFINES += -DRTOS
|
||||
WRAPPERSOURCES += targets/esp32/jswrap_rtos.c
|
||||
endif # RTOS
|
||||
endif # USE_ESP32
|
||||
|
||||
ifdef USE_ESP8266
|
||||
DEFINES += -DUSE_ESP8266
|
||||
WRAPPERSOURCES += libs/network/esp8266/jswrap_esp8266_network.c \
|
||||
@ -1419,7 +1454,7 @@ ifeq ($(FAMILY), NRF52)
|
||||
PRECOMPILED_OBJS += $(NRF5X_SDK_PATH)/components/toolchain/gcc/gcc_startup_nrf52.o
|
||||
|
||||
DEFINES += -DSWI_DISABLE0 -DSOFTDEVICE_PRESENT -DNRF52 -DCONFIG_GPIO_AS_PINRESET -DS132 -DBLE_STACK_SUPPORT_REQD
|
||||
DEFINES += -DNRF_SD_BLE_API_VERSION=3
|
||||
DEFINES += -DNRF_SD_BLE_API_VERSION=3
|
||||
|
||||
SOFTDEVICE = $(NRF5X_SDK_PATH)/components/softdevice/s132/hex/s132_nrf52_3.0.0_softdevice.hex
|
||||
|
||||
@ -1441,6 +1476,9 @@ ifeq ($(FAMILY), NRF52)
|
||||
# BLE HID Support (only NRF52)
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/ble/ble_services/ble_hids
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/ble/ble_services/ble_hids/ble_hids.c
|
||||
# Neopixel support (only NRF52)
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/i2s
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/drivers_nrf/i2s/nrf_drv_i2s.c
|
||||
|
||||
endif #FAMILY == NRF52
|
||||
|
||||
@ -1492,15 +1530,20 @@ ifdef NRF5X
|
||||
targets/nrf5x/bluetooth.c \
|
||||
targets/nrf5x/bluetooth_utils.c \
|
||||
targets/nrf5x/nrf5x_utils.c
|
||||
|
||||
ifeq ($(FAMILY), NRF52)
|
||||
# Neopixel support (only NRF52)
|
||||
SOURCES += targets/nrf5x/i2s_ws2812b_drive.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Careful here.. All these includes and sources assume a SoftDevice. Not efficeint/clean if softdevice (ble) is not enabled...
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/toolchain/cmsis/include
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/toolchain/gcc
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/toolchain
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/log
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/log/src
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/toolchain/cmsis/include
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/toolchain/gcc
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/toolchain
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/log
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/log/src
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/config
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/fstorage/config
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/util
|
||||
@ -1684,6 +1727,12 @@ ifeq ($(FAMILY), EFM32GG)
|
||||
|
||||
endif #FAMILY == EFM32
|
||||
|
||||
ifeq ($(FAMILY),ESP32)
|
||||
CFLAGS+=-Og -Wpointer-arith -Wno-error=unused-function -Wno-error=unused-but-set-variable \
|
||||
-Wno-error=unused-variable -Wall -ffunction-sections -fdata-sections -mlongcalls -nostdlib \
|
||||
-MMD -MP -std=gnu99 -fstrict-volatile-bitfields -fgnu89-inline
|
||||
SOURCES += targets/esp32/jshardware.c
|
||||
endif
|
||||
|
||||
ifeq ($(FAMILY),ESP8266)
|
||||
# move os_printf strings into flash to save RAM space
|
||||
@ -1844,6 +1893,101 @@ ifdef LINKER_FILE
|
||||
LDFLAGS += -T$(LINKER_FILE)
|
||||
endif
|
||||
|
||||
#
|
||||
# Definitions for the build of the ESP32
|
||||
#
|
||||
ifdef ESP32
|
||||
ifndef ESP_IDF_PATH
|
||||
$(error "The ESP_IDF_PATH variable must be set")
|
||||
endif
|
||||
ifndef ESP_APP_TEMPLATE_PATH
|
||||
$(error "The ESP_APP_TEMPLATE_PATH variable must be set")
|
||||
endif
|
||||
# The prefix for the ESP32 compiler
|
||||
CCPREFIX=xtensa-esp32-elf-
|
||||
SOURCES += targets/esp32/main.c
|
||||
LDFLAGS += -L$(ESP_IDF_PATH)/ld \
|
||||
-L$(ESP_IDF_PATH)/components/bt/lib \
|
||||
-L$(ESP_IDF_PATH)/components/esp32/lib \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/bootloader \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/bt \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/driver \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/esp32 \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/esptool_py \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/expat \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/freertos \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/json \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/log \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/lwip \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/mbedtls \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/newlib \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/nghttp \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/nvs_flash \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/partition_table \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/spi_flash \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/tcpip_adapter \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/vfs \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/newlib \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/wpa_supplicant \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/ethernet \
|
||||
-lgcc
|
||||
ESPTOOL?=
|
||||
INCLUDE+=\
|
||||
-I$(ESP_APP_TEMPLATE_PATH)/build/include \
|
||||
-I$(ESP_IDF_PATH)/components \
|
||||
-I$(ESP_IDF_PATH)/components/newlib/include \
|
||||
-I$(ESP_IDF_PATH)/components/bt/include \
|
||||
-I$(ESP_IDF_PATH)/components/driver/include \
|
||||
-I$(ESP_IDF_PATH)/components/esp32/include \
|
||||
-I$(ESP_IDF_PATH)/components/freertos/include \
|
||||
-I$(ESP_IDF_PATH)/components/json/include \
|
||||
-I$(ESP_IDF_PATH)/components/log/include \
|
||||
-I$(ESP_IDF_PATH)/components/lwip/include/lwip \
|
||||
-I$(ESP_IDF_PATH)/components/lwip/include/lwip/port \
|
||||
-I$(ESP_IDF_PATH)/components/lwip/include/lwip/posix \
|
||||
-I$(ESP_IDF_PATH)/components/newlib/include \
|
||||
-I$(ESP_IDF_PATH)/components/spi_flash/include \
|
||||
-I$(ESP_IDF_PATH)/components/nvs_flash/include \
|
||||
-I$(ESP_IDF_PATH)/components/tcpip_adapter/include \
|
||||
-I$(ESP_IDF_PATH)/components/vfs/include \
|
||||
-Itargets/esp32/include
|
||||
LDFLAGS+=-nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,-EL
|
||||
LIBS+=-T esp32_out.ld \
|
||||
-T$(ESP_IDF_PATH)/components/esp32/ld/esp32.common.ld \
|
||||
-T$(ESP_IDF_PATH)/components/esp32/ld/esp32.rom.ld \
|
||||
-T$(ESP_IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
|
||||
$(ESP_IDF_PATH)/components/newlib/lib/libc.a \
|
||||
$(ESP_IDF_PATH)/components/newlib/lib/libm.a \
|
||||
-lbt \
|
||||
-lbtdm_app \
|
||||
-ldriver \
|
||||
-lesp32 \
|
||||
$(ESP_IDF_PATH)/components/esp32/libhal.a \
|
||||
-lcore \
|
||||
-lnet80211 \
|
||||
-lphy \
|
||||
-lwpa_supplicant \
|
||||
-lrtc \
|
||||
-lpp \
|
||||
-lwpa \
|
||||
-lexpat \
|
||||
-lfreertos \
|
||||
-ljson \
|
||||
-llog \
|
||||
-llwip \
|
||||
-lmbedtls \
|
||||
-lnghttp \
|
||||
-lnvs_flash \
|
||||
-lspi_flash \
|
||||
-ltcpip_adapter \
|
||||
-lvfs \
|
||||
-lnewlib \
|
||||
-lcoexist \
|
||||
-lethernet \
|
||||
-lstdc++ \
|
||||
-lgcc
|
||||
endif # ESP32
|
||||
|
||||
#
|
||||
# Definitions for the build of the ESP8266
|
||||
#
|
||||
@ -1989,6 +2133,53 @@ proj: $(PLATFORM_CONFIG_FILE) $(PROJ_NAME)
|
||||
$(PROJ_NAME): $(OBJS)
|
||||
@echo $($(quiet_)link)
|
||||
@$(call link)
|
||||
|
||||
# Linking for ESP32
|
||||
else ifdef ESP32
|
||||
|
||||
ESP_ZIP = $(PROJ_NAME).tgz
|
||||
|
||||
espruino_esp32.bin: $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o espruino_esp32.elf -Wl,--start-group $(LIBS) $(OBJS) -Wl,--end-group
|
||||
python $(ESP_IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
elf2image \
|
||||
--flash_mode "dio" \
|
||||
--flash_freq "40m" \
|
||||
-o espruino_esp32.bin \
|
||||
espruino_esp32.elf
|
||||
|
||||
$(ESP_ZIP): espruino_esp32.bin
|
||||
$(Q)rm -rf build/$(basename $(ESP_ZIP))
|
||||
$(Q)mkdir -p build/$(basename $(ESP_ZIP))
|
||||
$(Q)cp $(ESP_APP_TEMPLATE_PATH)/build/bootloader/bootloader.bin \
|
||||
espruino_esp32.bin \
|
||||
$(ESP_APP_TEMPLATE_PATH)/build/partitions_singleapp.bin \
|
||||
targets/esp32/README_flash.txt \
|
||||
build/$(basename $(ESP_ZIP))
|
||||
$(Q)tar -C build -zcf $(ESP_ZIP) ./$(basename $(ESP_ZIP))
|
||||
|
||||
proj: espruino_esp32.bin $(ESP_ZIP)
|
||||
|
||||
flash:
|
||||
python $(ESP_IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
--port "/dev/ttyUSB0" \
|
||||
--baud 921600 \
|
||||
write_flash \
|
||||
-z \
|
||||
--flash_mode "dio" \
|
||||
--flash_freq "40m" \
|
||||
0x1000 $(ESP_APP_TEMPLATE_PATH)/build/bootloader/bootloader.bin \
|
||||
0x10000 espruino_esp32.bin \
|
||||
0x8000 $(ESP_APP_TEMPLATE_PATH)/build/partitions_singleapp.bin
|
||||
|
||||
erase_flash:
|
||||
python $(ESP_IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
--port "/dev/ttyUSB0" \
|
||||
--baud 921600 \
|
||||
erase_flash
|
||||
|
||||
else ifdef ESP8266
|
||||
# Linking the esp8266... The Espruino source files get compiled into the .text section. The
|
||||
|
||||
@ -87,13 +87,17 @@ If you are a board manufacturer interested in getting your board officially supp
|
||||
|
||||
* [Original Espruino Board](http://www.espruino.com/EspruinoBoard) - great support.
|
||||
* [Espruino Pico Board](http://www.espruino.com/Pico) - great support.
|
||||
* [Puck.js](http://www.espruino.com/Puck.js) - great support.
|
||||
* [Espruino WiFi Board](http://www.espruino.com/WiFi) - great support.
|
||||
* Linux - WORKING
|
||||
* [BBC micro:bit](http://www.espruino.com/MicroBit) - WORKING
|
||||
* [STM32VLDISCOVERY](http://www.espruino.com/ReferenceSTM32VLDISCOVERY) - WORKING - limited memory so some features removed
|
||||
* [STM32F3DISCOVERY](http://www.espruino.com/ReferenceSTM32F3DISCOVERY) - USB BROKEN
|
||||
* [STM32F4DISCOVERY](http://www.espruino.com/ReferenceSTM32F4DISCOVERY) - WORKING
|
||||
* STM32F401CDISCOVERY - appears WORKING, but very little testing done
|
||||
* STM32F429IDISCOVERY - WORKING over serial (A9/A10). No USB and no LCD support
|
||||
* NRF52832 Preview Development Kit - WORKING with limited functionality. Able to interface with Espruino over BLE (send commands from smartphone or computer) or serial as normal (send commands from chrome IDE or terminal).
|
||||
* NRF51822 Development Kit - WORKING
|
||||
* NRF52832 Development Kit - WORKING
|
||||
* [HY STM32 2.4"](http://www.espruino.com/ReferenceHYSTM32_24) - WORKING
|
||||
* [HY STM32 2.8"](http://www.espruino.com/ReferenceHYSTM32_28) - WORKING - limited memory so some features removed
|
||||
* [HY STM32 3.2"](http://www.espruino.com/ReferenceHYSTM32_32) - WORKING
|
||||
@ -104,8 +108,7 @@ If you are a board manufacturer interested in getting your board officially supp
|
||||
* LC-TECH STM32F103RBT6 - WORKING, but with some issues (LED inverted logic, BTN needs pullup to work)
|
||||
* [ST NUCLEO-F401RE](http://www.espruino.com/ReferenceNUCLEOF401RE) - WORKING
|
||||
* ST NUCLEO-F411RE - WORKING
|
||||
* ESP8266 - Beta - Reasonably stable, but expect to find issues
|
||||
* NRF51/52 - Alpha - very early in development (GPIO, but not peripherals, no sleep or save)
|
||||
* ESP8266 - WORKING - Reasonably stable, but expect to find issues
|
||||
* Arduino (AVR) - NOT POSSIBLE due to the Hardward architecture of AVRs, even though it would fit into an ATMEGA2560. If `avr-gcc` ever gains an easy way to emulate Von Neumann architecture then it might be portable, but for now it isn't.
|
||||
* Arduino (ARM) - very doable, but no work has been done on this.
|
||||
|
||||
|
||||
@ -1,24 +1,111 @@
|
||||
Building
|
||||
========
|
||||
# Building
|
||||
|
||||
**Note:** If you're swapping between compiling for different targets, **you
|
||||
need to call `make clean`** before you compile for the new target.
|
||||
There are several options to building Espruino on various platforms for the OS and board versions that are avaiable.
|
||||
|
||||
Under Linux
|
||||
-----------
|
||||
To build, and run, Espruino on the OS that one is using is as simple as the following, if prerequisits are met:
|
||||
|
||||
Espruino is easy to build under Linux, and it is possible to build under MacOS with some effort. If you don't have Linux it's **much** easier to install it in a Virtual Machine. See the heading **Building under Windows/MacOS with a VM** below for more information.
|
||||
```bash
|
||||
make clean && make
|
||||
```
|
||||
|
||||
### for STM32 Boards (incl. [Espruino Board](http://www.espruino.com/EspruinoBoard))
|
||||
**Note:**
|
||||
|
||||
The (previously suggested) CodeSourcery GCC compiler is no longer available. We'd suggest you use [gcc-arm-none-eabi](https://launchpad.net/gcc-arm-embedded/+download).
|
||||
* In general, have a look through the Makefile to see what other options are available
|
||||
* If you're swapping between compiling for different targets, you need to call `make clean` before you compile for the new target.
|
||||
* If you have a ld error, check the board name in the BOARDNAME=1 make in the Makefile.
|
||||
* ```RELEASE=1``` for performance and code size, without it, assertions are kept for debugging.
|
||||
* ```DEBUG=1``` is available.
|
||||
|
||||
Download the compiler, set up your path so you have access to it, and run:
|
||||
## Under Linux
|
||||
|
||||
```YOUR_BOARD_NAME=1 RELEASE=1 make```
|
||||
Espruino is easy to build under Linux, for either for Espruino running on Linux or a board.
|
||||
|
||||
The current reference OS for building is Ubuntu 16.04.1 LTS, and the following can ensure problem free development:
|
||||
|
||||
### for Espruino
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential git python python-pip
|
||||
sudo pip install --upgrade pip
|
||||
# User choice for placement of source repos
|
||||
mkdir -p ~/source/repos/github/espruino
|
||||
cd ~/source/repos/github/espruino
|
||||
git clone https://github.com/espruino/Espruino.git
|
||||
cd Espruino
|
||||
make clean && make
|
||||
chmod +x espruino && sudo cp espruino /usr/local/bin
|
||||
```
|
||||
|
||||
### for an example of cross compilation for the puck.js
|
||||
|
||||
Having successfully created an native OS Espruino, try a cross compilation.
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo pip install nrfutil
|
||||
sudo apt-get install -y \
|
||||
lib32z1 lib32ncurses5
|
||||
wget https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update/+download/gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2
|
||||
tar xjf gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2
|
||||
sudo mv gcc-arm-none-eabi-5_4-2016q3-20160926 /usr/local
|
||||
export PATH=/usr/local/gcc-arm-none-eabi-5_4-2016q3/bin:$PATH
|
||||
cd ~/source/repos/github/espruino/Espruino
|
||||
make clean && DFU_UPDATE_BUILD=1 PUCKJS=1 RELEASE=1 make
|
||||
ls -l *puckjs*
|
||||
```
|
||||
|
||||
## Under MacOS
|
||||
|
||||
* It is possible to build Espruino under MacOS with some effort.
|
||||
* PR for an easy Espruino build under MacOS are welcome.
|
||||
* If you don't have Linux it's much easier to install it in a Virtual Machine (see below).
|
||||
|
||||
## Under Windows
|
||||
|
||||
It is possible to build Espruino under Windows with the following addition to the Linux explanation:
|
||||
|
||||
* Install Bash on Ubuntu on Windows 10 <https://msdn.microsoft.com/da-dk/commandline/wsl/install_guide>
|
||||
* After enabling, just use the instructions for Linux
|
||||
|
||||
Note:
|
||||
|
||||
* there is no access to USB in the present version
|
||||
* copy any crosscompile output to one's user directory and either bluetooth or USB the result to the target
|
||||
* Ubuntu 14.04 LTS is the present version.
|
||||
|
||||
Or use a Virtual machine as described below dependent on ones taste.
|
||||
|
||||
## Cross compilation
|
||||
|
||||
### for Raspberry Pi
|
||||
|
||||
Using [RASPBIAN JESSIE WITH PIXEL](https://www.raspberrypi.org/downloads/raspbian/), getting Espruino is easy.
|
||||
|
||||
To enable the full power of Espruino on the Pi, [WiringPi](http://wiringpi.com/):
|
||||
|
||||
* ```sudo apt-get install wiringpi```
|
||||
|
||||
Getting Espruino:
|
||||
|
||||
* clone this repository and cd into the directory
|
||||
* ```make clean && make```
|
||||
* ```chmod +x espruino && sudo cp espruino /usr/local/bin```
|
||||
|
||||
### for OpenWRT
|
||||
|
||||
Follow the instructions for [OpenWRT build system](https://wiki.openwrt.org/doc/howto/buildroot.exigence)
|
||||
|
||||
After a successful OpenWRT build, [OpenWRT Espruino packages](https://github.com/vshymanskyy/OpenWRT-Espruino-packages)
|
||||
|
||||
### for STM32 Boards (incl. [Espruino Board](http://www.espruino.com/EspruinoBoard)
|
||||
|
||||
```bash
|
||||
make clean && YOUR_BOARD_NAME=1 RELEASE=1 make
|
||||
```
|
||||
|
||||
* See the top of Makefile for board names
|
||||
* Without `RELEASE=1`, assertions are kept in the code (which is good for debugging, bad for performance + code size)
|
||||
* `BOARDNAME=1 RELEASE=1 make serialflash` will flash to /dev/ttyUSB0 using the STM32 serial bootloader (what's needed for the Espruino and HY boards)
|
||||
* `BOARDNAME=1 RELEASE=1 make flash` will flash using st-flash if it's a discovery board, the maple bootloader if using that board, or will copy the binary to `/media/NUCLEO` if using a Nucleo board.
|
||||
|
||||
@ -27,39 +114,64 @@ It may complain that there isn't enough space on the chip. This isn't an issue u
|
||||
* Disable the check by adding `TRAVIS=1`
|
||||
* Change the compile flags from `-O3` to `-Os` in the `Makefile`
|
||||
* Knock out some functionality (like `USE_GRAPHICS=1`) that you don't need in the `Makefile`
|
||||
* Try different compilers. `codesourcery-2013.05-23-arm-none-eabi` provides low binary size for `-O3`
|
||||
|
||||
**Note:** Espruino boards contain a special bootloader at `0x08000000` (the default address), with the Espruino binary moved on 10240 bytes to `0x08002800`. To load the Espruino binary onto a board at the correct address, use `ESPRUINO_1V3=1 RELEASE=1 make serialflash`. If you want to make a binary that contains the bootloader as well as Espruino (like the ones that the Espruino Web IDE expects to use) use the script `scripts/create_espruino_image_1v3.sh` which will compile the bootloader *and* Espruino, and then join them together.
|
||||
|
||||
----
|
||||
### for [Nordic Semiconductor's nRF51/nRF52 series devices](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy)
|
||||
|
||||
### for Nordic Semiconductor's nRF51/nRF52 series devices
|
||||
Dependant on the board, either usb or bluetooth can be used to program the board or install the bootloader from different devices.
|
||||
|
||||
The (previously suggested) CodeSourcery GCC compiler is no longer available. We'd suggest you use [gcc-arm-none-eabi](https://launchpad.net/gcc-arm-embedded/+download).
|
||||
* Bluetooth Low energy
|
||||
* the board will appear as `Espruino XYZ` where `XYZ` is the board name
|
||||
* USB
|
||||
* the board appears as a drive to drop a hex on
|
||||
|
||||
Download the compiler, set up your path so you have access to it, and run:
|
||||
#### for [puck.js](http://www.espruino.com/Puck.js)
|
||||
|
||||
```NRF52832DK=1 RELEASE=1 make```
|
||||
The puck.js is based on the nRF52
|
||||
|
||||
**Note:** This is for the nRF52 devkit, use `NRF51822DK=1` instead for the nRF51 devkit, `MICROBIT=1` for the BBC micro:bit, or check the first 50-ish lines of the `Makefile` for more board options.
|
||||
```bash
|
||||
make clean && DFU_UPDATE_BUILD=1 PUCKJS=1 RELEASE=1 make
|
||||
```
|
||||
|
||||
To program the nRF52 Development Kit with Espruino, type `NRF52832DK=1 RELEASE=1 make flash` on Linux. This will copy the generated `espruino_xx.xx_nrf52832.hex` file to the nRF devkit's USB flash drive - you can however do that manually if you want to.
|
||||
The resulting file is a zip that has to be transferred to the puck.js via a Bluetooth low energy device.
|
||||
See <https://www.espruino.com/Puck.js+Quick+Start> for information concerning transferring the zip to the puck.js.
|
||||
|
||||
Now Espruino is ready to use - you can either use [the Web IDE](http://www.espruino.com/Quick+Start) to connect, or you can use any serial terminal application as long as you connect at 9600 baud (no parity, 1 stop bit).
|
||||
#### for [NRF52-DK](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK)
|
||||
|
||||
You can also connect via Bluetooth Low energy - the board will appear as `Espruino XYZ` where `XYZ` is the board name:
|
||||
All boards based on the nRF52 have RAM and Flash to support Espruino without feature disablement.
|
||||
|
||||
* Use the Nordic UART Android app - install it, connect to the device, and then issue commands. Note that you will have to explicitly send a Carriage Return at the end of any command in order or it to execute (eg. `1+2 [newline]` then click send)
|
||||
```bash
|
||||
make clean && NRF52832DK=1 RELEASE=1 make
|
||||
```
|
||||
|
||||
* Use Web Bluetooth - see [The BBC micro:bit page](http://www.espruino.com/MicroBit) for more information about this.
|
||||
#### for [micro:bit](http://microbit.org/)
|
||||
|
||||
----
|
||||
The micro:bit is based on the nRF51.
|
||||
|
||||
* ```make clean && MICROBIT=1 RELEASE=1 make```
|
||||
* Drop the hex generated on the micro:bit drive and it is then an Espruino.
|
||||
|
||||
Note:
|
||||
|
||||
* At the time of writing, if one uses the [Espruino Web IDE](https://www.espruino.com/Web+IDE), access the Settings->Communications
|
||||
* Request board details on connect: false
|
||||
* Throttle Send: true
|
||||
|
||||
#### for [NRF51-DK](https://www.nordicsemi.com/eng/Products/nRF51-DK)
|
||||
|
||||
All boards based on the nRF51 are limited in RAM and Flash so many features are disabled.
|
||||
|
||||
```bash
|
||||
make clean && NRF51822DK=1 RELEASE=1 make
|
||||
```
|
||||
|
||||
### for esp8266
|
||||
|
||||
In order to compile for the esp8266 on Linux several pre-requisites have to be installed:
|
||||
- the esp-open-sdk from https://github.com/pfalcon/esp-open-sdk, use make STANDALONE=n
|
||||
- the Espressif SDK (version 1.5.0 with lwip patch as of this writing) from http://bbs.espressif.com/viewforum.php?f=46 and http://bbs.espressif.com/viewtopic.php?f=7&t=1528
|
||||
|
||||
* the esp-open-sdk from <https://github.com/pfalcon/esp-open-sdk>, use make STANDALONE=n
|
||||
* the Espressif SDK (version 1.5.0 with lwip patch as of this writing) from <http://bbs.espressif.com/viewforum.php?f=46> and <http://bbs.espressif.com/viewtopic.php?f=7&t=1528>
|
||||
|
||||
To run make you need to pass a couple of environment variables to `make`. These include:
|
||||
|
||||
@ -69,16 +181,18 @@ To run make you need to pass a couple of environment variables to `make`. These
|
||||
* `PATH=<Path to esp-open-sdk/xtensa-lx106-elf/bin/>`
|
||||
* `COMPORT=</dev/ttyUSB0|COM1|...>`
|
||||
|
||||
The easiest is to place
|
||||
the following lines into a script, adapt it to your needs and then run it.
|
||||
```
|
||||
The easiest is to place the following lines into a script, adapt it to your needs and then run it.
|
||||
|
||||
```bash
|
||||
|
||||
#! /bin/bash
|
||||
export ESP8266_BOARD=1
|
||||
export FLASH_4MB=1
|
||||
export ESP8266_SDK_ROOT=/esp8266/esp_iot_sdk_v1.5.0
|
||||
export PATH=$PATH:/esp8266/esp-open-sdk/xtensa-lx106-elf/bin/
|
||||
export COMPORT=/dev/ttyUSB0
|
||||
make $*
|
||||
make clean && make $*
|
||||
|
||||
```
|
||||
|
||||
* If you do `make flash` it will try to flash your esp8266 module over serial
|
||||
@ -87,13 +201,12 @@ make $*
|
||||
* You will also get an `espruino_1v00_*_esp8266.tgz` archive, which contains everything you
|
||||
need to flash a module (except for esptool.py), including a README_flash.txt
|
||||
|
||||
####Building on Eclipse
|
||||
#### Building on Eclipse
|
||||
|
||||
When building on Eclipse, update the Makefile properties to include the definitions show above. The easiest way to achieve
|
||||
that task is to right-click your Espruino project and select `properties`. From there, navigate to `C/C++ Build > Environment`.
|
||||
|
||||
----
|
||||
|
||||
### for EMW3165
|
||||
#### for EMW3165
|
||||
|
||||
Note: the emw3165 port is very preliminary and does not include Wifi support at this time.
|
||||
_The text below is what is planned in order to support Wifi, but it doesn't exist yet._
|
||||
@ -109,120 +222,99 @@ The strategy employed is to compile portions of WICED into a library using the W
|
||||
and then linking this into Espruino.
|
||||
|
||||
Setting up WICED:
|
||||
- WICED does not officially support the EMW3165.
|
||||
- Clone https://github.com/MXCHIP-EMW/WICED-for-EMW and follow the instructions there to configure
|
||||
|
||||
* WICED does not officially support the EMW3165.
|
||||
* Clone <https://github.com/MXCHIP-EMW/WICED-for-EMW> and follow the instructions there to configure
|
||||
WICED and build it. (You will need to sign up for a developer acct with Broadcom.)
|
||||
- Build the apsta sample program (snippet) using a command-line like
|
||||
* Build the apsta sample program (snippet) using a command-line like
|
||||
`./make EMW3165-FreeRTOS-LwIP-snip.apsta download run JTAG=stlink-v2`
|
||||
- Hook up your emw3165 to an ST-Link-v2 or your preferred STM32 programmer and flash using the
|
||||
* Hook up your emw3165 to an ST-Link-v2 or your preferred STM32 programmer and flash using the
|
||||
above command-line. You should see the EMW's access point.
|
||||
- An alternative program to test with is the "scan" snip as it will also print something on the
|
||||
* An alternative program to test with is the "scan" snip as it will also print something on the
|
||||
console (works well with the WifiMCU board): `./make EMW3165-FreeRTOS-LwIP-snip.scan ...`
|
||||
|
||||
Compiling WICED into a library:
|
||||
- ... if only this worked ...
|
||||
|
||||
* ... if only this worked ...
|
||||
|
||||
Compiling Espruino:
|
||||
- To compile Espruino you will need to point to the WICED root and include files. This is
|
||||
|
||||
* To compile Espruino you will need to point to the WICED root and include files. This is
|
||||
done by specifying a WICED_ROOT environment variable.
|
||||
- Adapt the pathnames from the following script:
|
||||
```
|
||||
* Adapt the pathnames from the following script:
|
||||
|
||||
```bash
|
||||
|
||||
WICED_ROOT=/home/emw3165/WICED-for-EMW/WICED-SDK-3.3.1 make $*
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### for Linux
|
||||
|
||||
Simple: Just run `make`
|
||||
|
||||
----
|
||||
|
||||
### for Raspberry Pi
|
||||
|
||||
On the Pi, just run `make`.
|
||||
|
||||
Or to cross-compile:
|
||||
|
||||
```
|
||||
cd targetlibs
|
||||
mkdir raspberrypi
|
||||
cd raspberrypi
|
||||
git clone git://github.com/raspberrypi/tools.git
|
||||
sudo apt-get install ia32-libs
|
||||
|
||||
## Documentation
|
||||
|
||||
```bash
|
||||
|
||||
sudo pip install markdown
|
||||
python scripts/build_docs.py
|
||||
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### for Carambola (OpenWRT)
|
||||
|
||||
To cross compile,
|
||||
|
||||
* Follow instructions at <https://github.com/8devices/carambola> to set toolchain up in ```~/workspace/carambola```
|
||||
* Run ```CARAMBOLA=1 make```
|
||||
|
||||
----
|
||||
|
||||
### Documentation
|
||||
|
||||
```python scripts/build_docs.py ```
|
||||
|
||||
This will create a file called ```functions.html``` that is a version of [the reference pages](http://www.espruino.com/Reference),
|
||||
but based on your source code.
|
||||
|
||||
----
|
||||
## Virtual Machines under Windows and MacOS
|
||||
|
||||
Building under Windows/MacOS with a VM (Vagrant)
|
||||
------------------------------------------------
|
||||
The easiest solution for a Virtual Machine for Windows and MacOS is [VirtualBox](https://www.virtualbox.org/).
|
||||
A really easy way to provision, ie setup the system for development, is [Vagrant](https://www.vagrantup.com).
|
||||
|
||||
* Clone this repository.
|
||||
* Download and install the correct [VirtualBox](https://www.virtualbox.org/) for your platform. eg. If you have Windows, download 'VirtualBox for Windows Hosts'.
|
||||
* Download and install the correct [Vagrant](https://www.vagrantup.com/downloads.html) for your platform.
|
||||
> If running on MacOS, the two previous steps can be accomplished easily with [Homebrew Cask](http://caskroom.io): `brew cask install virtualbox vagrant` will do it.
|
||||
* In your terminal application, navigate to your cloned working copy.
|
||||
* Install the auto-network plugin with `vagrant plugin install vagrant-auto_network`
|
||||
* Execute `vagrant up`. This will take a little while while the box is downloaded, and your virtual machine is provisioned.
|
||||
* When it is complete, execute `vagrant ssh`, which will open an ssh session into your new VM.
|
||||
* Execute `cd /vagrant && ESPRUINO_1V3=1 RELEASE=1 make` and wait.
|
||||
* Espruino is now built. See the documentation under **Building under Linux** for more examples.
|
||||
* To terminate the ssh session, simply execute `exit`.
|
||||
* `vagrant suspend` will pause the VM, `vagrant halt` will stop it, and `vagrant up` will bring it back up again. See Vagrant's ["Getting Started"](http://docs.vagrantup.com/v2/getting-started/index.html) page for further information.
|
||||
Note:
|
||||
|
||||
----
|
||||
* Windows
|
||||
* Installation of <https://git-scm.com/> gives a ssh that can be used with vagrant ssh
|
||||
|
||||
Building under Windows/MacOS with a VM
|
||||
--------------------------------------
|
||||
### Vagrant and VirtualBox
|
||||
|
||||
* Download and install the correct [VirtualBox](https://www.virtualbox.org/) for your platform. eg. If you have Windows, download 'VirtualBox for Windows Hosts'.
|
||||
* Download the [Ubuntu 14.04 32 bit Desktop ISO Image](http://www.ubuntu.com/download/desktop)
|
||||
* Run VirtualBox, and click the 'New' button
|
||||
* Give the new OS a name, choose `Linux` as the type, and `Ubuntu (32 bit)` as the version
|
||||
* Click `Next`, choose 2048MB of memory, and not to create a hard disk image (ignore the warning). **Note:** We're going to run Ubuntu right from the virtual CD without installing (because it's a bit faster and easier). If you have time you might want to create a hard disk image (you won't need as much memory then) and then choose to install Ubuntu when given the chance.
|
||||
* Click start, and when prompted for a CD image choose the Ubuntu ISO you downloaded
|
||||
* Wait until a picture of a keyboard appears at the bottom of the screen, then press enter
|
||||
* Select a language, and then choose `Try Ubuntu` with the arrow keys
|
||||
* When it's booted, press Alt-F2, type `gnome-terminal`, then enter. **Note:** You could also just press Ctrl-Alt-F2 to get a faster but less shiny-looking terminal window.
|
||||
* In the terminal, type: `sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded` and press enter when prompted
|
||||
* Type `sudo apt-get update`
|
||||
* Type `sudo apt-get install gcc-arm-none-eabi git` and press 'Y' if prompted
|
||||
* Type `git clone https://github.com/espruino/Espruino.git`
|
||||
* Type `cd Espruino`
|
||||
* Type `ESPRUINO_1V3=1 RELEASE=1 make` and wait
|
||||
* Espruino is now built. See the documentation under **Building under Linux** for more examples.
|
||||
* When you exit the VM, make sure you choose `Save State`. If you `Power Off` you will lose everything you've done so far.
|
||||
* For your host OS (Windows or MacOS)
|
||||
* Download and install [VirtualBox](https://www.virtualbox.org/)
|
||||
* Download and install [Vagrant](https://www.vagrantup.com/downloads.html)
|
||||
* Note: for MacOS, the two previous steps can be accomplished easily with [Homebrew Cask](http://caskroom.io)
|
||||
* `brew cask install virtualbox vagrant`
|
||||
* Clone this repository and navigate with the command prompt to the contents
|
||||
* Install the auto-network plugin
|
||||
* `vagrant plugin install vagrant-auto_network`
|
||||
* Execute
|
||||
* `vagrant up`
|
||||
* This will take a little while while the box is downloaded, and your virtual machine is provisioned.
|
||||
* `vagrant ssh`
|
||||
* a ssh session into your new VM will be created.
|
||||
* `cd /vagrant && make clean && make`
|
||||
* a native OS version of Espruino is now built. See this documentation for further examples
|
||||
* To exit the ssh session
|
||||
*`exit`.
|
||||
* On the host OS, the following are useful vagrant commands
|
||||
* `vagrant suspend`
|
||||
* will pause the VM
|
||||
* `vagrant halt`
|
||||
* will stop the VM
|
||||
* See Vagrant's ["Getting Started"](https://www.vagrantup.com/docs/getting-started/index.html) page for further information.
|
||||
|
||||
There's some more information on how to do this on the forum at http://forum.espruino.com/conversations/151 including links to a pre-made [Amazon EC2 instance](http://forum.espruino.com/conversations/151/?offset=25#comment20326).
|
||||
### VirtualBox
|
||||
|
||||
----
|
||||
If one does not wish to use vagrant, then install Virtual Box and use the Linux method.
|
||||
|
||||
## USB access
|
||||
|
||||
In order to access USB, bluetooth or connected USB devices, one has USB filters to dedicate access to the guest OS.
|
||||
The easiest method is via the VirtualBox Manager, and select which devices should be dedicated to the VM with the device filter.
|
||||
Note: VirtualBox Guest Additions from VirtualBox are required.
|
||||
|
||||
### To flash Espruino from the VM
|
||||
|
||||
* Plug the Espruino board in while holding BTN1, and wait for Windows to finish connecting to the USB device
|
||||
* Go into the VirtualBox Manager (There's no need to stop your VM)
|
||||
* Click on `USB`, then click on the icon with the `+` sign (With the tooltip 'Adds a new USB filter ... selected USB device')
|
||||
* Click on the device labelled `STMicroelectronics STM32 ...`
|
||||
* Click on the device labeled `STMicroelectronics STM32 ...`
|
||||
* Now unplug the Espruino board, wait a few seconds, and plug it back in (holding BTN1 again)
|
||||
* Go back into the VM, and type `sudo ESPRUINO_1V3=1 RELEASE=1 make serialflash`
|
||||
* Your board will now be flashed
|
||||
|
||||
**Note:** if you want to you can change permissions so you don't need `sudo` by typing `sudo cp misc/45-espruino.rules /etc/udev/rules.d;sudo udevadm control --reload-rules` and then re-inserting the board.
|
||||
**Note:** if you want to you can change permissions so you don't need `sudo` by typing `sudo cp misc/45-espruino.rules /etc/udev/rules.d;sudo udevadm control --reload-rules` and then re-inserting the board.
|
||||
@ -24,7 +24,7 @@ info = {
|
||||
'build' : {
|
||||
'defines' : [
|
||||
'USE_NET',
|
||||
'USE_TELNET',
|
||||
'USE_TELNET',
|
||||
'USE_GRAPHICS',
|
||||
'USE_CRYPTO',
|
||||
'USE_TLS'
|
||||
@ -55,7 +55,11 @@ devices = {
|
||||
|
||||
# left-right, or top-bottom order
|
||||
board_esp32 = {
|
||||
<<<<<<< HEAD
|
||||
'top' : [ 'D0','D4','D16','D17','D5','D18','D19','D20','D21','D3','D1','D22','D23','GND'],
|
||||
=======
|
||||
'top' : ['GND','D23','D22','D1','D3','D21','D20','D19','D18','D5','D17','D16','D4','D0'],
|
||||
>>>>>>> 761dbafbae2ed426fc38a5b417031b815860ba83
|
||||
'bottom' : ['D12','D14','D27','D26','D25','D33','D32','D35','D34','D39','D36','EN','3V3','GND'],
|
||||
'right' : [ 'GND','D13','D9','D10','D11','D6','D7','D8','D15','D2']
|
||||
};
|
||||
@ -66,11 +70,19 @@ board_esp32["_css"] = """
|
||||
width: 600px;
|
||||
height: 435px;
|
||||
left: 50px;
|
||||
<<<<<<< HEAD
|
||||
top: 150px;
|
||||
background-image: url(img/ESP32.jpg);
|
||||
}
|
||||
#boardcontainer {
|
||||
height: 675px;
|
||||
=======
|
||||
top: 170px;
|
||||
background-image: url(img/ESP32.jpg);
|
||||
}
|
||||
#boardcontainer {
|
||||
height: 700px;
|
||||
>>>>>>> 761dbafbae2ed426fc38a5b417031b815860ba83
|
||||
}
|
||||
#board #right {
|
||||
top: 80px;
|
||||
@ -78,11 +90,19 @@ board_esp32["_css"] = """
|
||||
}
|
||||
#board #top {
|
||||
bottom: 440px;
|
||||
<<<<<<< HEAD
|
||||
left: 157px;
|
||||
}
|
||||
#board #bottom {
|
||||
top: 435px;
|
||||
left: 157px;
|
||||
=======
|
||||
left: 155px;
|
||||
}
|
||||
#board #bottom {
|
||||
top: 435px;
|
||||
left: 155px;
|
||||
>>>>>>> 761dbafbae2ed426fc38a5b417031b815860ba83
|
||||
}
|
||||
#board .rightpin {
|
||||
height: 28px;
|
||||
@ -96,6 +116,7 @@ boards = [ board_esp32 ];
|
||||
|
||||
def get_pins():
|
||||
|
||||
<<<<<<< HEAD
|
||||
pins = pinutils.generate_pins(0,5);
|
||||
#6-11 are used by Flash chip
|
||||
pins.extend(pinutils.generate_pins(12,23));
|
||||
@ -106,6 +127,24 @@ def get_pins():
|
||||
|
||||
pins = pinutils.fill_gaps_in_pin_list(pins);
|
||||
|
||||
=======
|
||||
|
||||
# { "name":"PD20", "sortingname":"D20", "port":"D", "num":"30", "functions":{ "I2C1_SDA":0 }, "csv":{} },
|
||||
|
||||
|
||||
# pins = pinutils.generate_pins(0,5);
|
||||
##6-11 are used by Flash chip
|
||||
# pins.extend(pinutils.generate_pins(12,23));
|
||||
|
||||
# pins.extend(pinutils.generate_pins(25,27));
|
||||
##32-33 are routed to rtc for xtal
|
||||
# pins.extend(pinutils.generate_pins(34,39));
|
||||
|
||||
# pins = pinutils.fill_gaps_in_pin_list(pins);
|
||||
|
||||
pins = pinutils.generate_pins(0,39) # 40 General Purpose I/O Pins.
|
||||
|
||||
>>>>>>> 761dbafbae2ed426fc38a5b417031b815860ba83
|
||||
pinutils.findpin(pins, "PD36", True)["functions"]["ADC1_IN0"]=0;
|
||||
pinutils.findpin(pins, "PD37", True)["functions"]["ADC1_IN1"]=0;
|
||||
pinutils.findpin(pins, "PD38", True)["functions"]["ADC1_IN2"]=0;
|
||||
@ -132,8 +171,19 @@ def get_pins():
|
||||
pinutils.findpin(pins, "PD0", True)["functions"]["LED_1"]=0;
|
||||
|
||||
pinutils.findpin(pins, "PD10", True)["functions"]["USART0_TX"]=0;
|
||||
<<<<<<< HEAD
|
||||
pinutils.findpin(pins, "PD16", True)["functions"]["UARTT2_RX"]=0;
|
||||
pinutils.findpin(pins, "PD17", True)["functions"]["USART2_TX"]=0;
|
||||
pinutils.findpin(pins, "PD32", True)["functions"]["USART0_RX"]=0;
|
||||
|
||||
return pins
|
||||
return pins
|
||||
=======
|
||||
pinutils.findpin(pins, "PD16", True)["functions"]["USART2_RX"]=0;
|
||||
pinutils.findpin(pins, "PD17", True)["functions"]["USART2_TX"]=0;
|
||||
pinutils.findpin(pins, "PD32", True)["functions"]["USART0_RX"]=0;
|
||||
|
||||
# everything is non-5v tolerant
|
||||
#for pin in pins:
|
||||
# pin["functions"]["3.3"]=0;
|
||||
return pins
|
||||
>>>>>>> 761dbafbae2ed426fc38a5b417031b815860ba83
|
||||
|
||||
@ -23,7 +23,7 @@ info = {
|
||||
'default_console_tx' : "H0", # pin 24
|
||||
'default_console_rx' : "H1", # pin 25
|
||||
'default_console_baudrate' : "9600",
|
||||
'variables' : 350,
|
||||
'variables' : 300,
|
||||
'binary_name' : 'espruino_%v_microbit.hex',
|
||||
'build' : {
|
||||
'defines' : [
|
||||
@ -123,4 +123,7 @@ def get_pins():
|
||||
{ "name":"PH0", "sortingname":"H0", "port":"D", "num":"24", "functions":{}, "csv":{} },
|
||||
{ "name":"PH1", "sortingname":"H1", "port":"D", "num":"25", "functions":{}, "csv":{} }
|
||||
];
|
||||
# everything is non-5v tolerant
|
||||
for pin in pins:
|
||||
pin["functions"]["3.3"]=0;
|
||||
return pins
|
||||
|
||||
@ -101,6 +101,9 @@ def get_pins():
|
||||
pinutils.findpin(pins, "PD4", True)["functions"]["ADC1_IN5"]=0;
|
||||
pinutils.findpin(pins, "PD5", True)["functions"]["ADC1_IN6"]=0;
|
||||
pinutils.findpin(pins, "PD6", True)["functions"]["ADC1_IN7"]=0;
|
||||
# everything is non-5v tolerant
|
||||
for pin in pins:
|
||||
pin["functions"]["3.3"]=0;
|
||||
|
||||
#The boot/reset button will function as a reset button in normal operation. Pin reset on PD21 needs to be enabled on the nRF52832 device for this to work.
|
||||
return pins
|
||||
|
||||
@ -103,5 +103,8 @@ def get_pins():
|
||||
pinutils.findpin(pins, "PD29", True)["functions"]["ADC1_IN5"]=0;
|
||||
pinutils.findpin(pins, "PD30", True)["functions"]["ADC1_IN6"]=0;
|
||||
pinutils.findpin(pins, "PD31", True)["functions"]["ADC1_IN7"]=0;
|
||||
# everything is non-5v tolerant
|
||||
for pin in pins:
|
||||
pin["functions"]["3.3"]=0;
|
||||
#The boot/reset button will function as a reset button in normal operation. Pin reset on PD21 needs to be enabled on the nRF52832 device for this to work.
|
||||
return pins
|
||||
|
||||
@ -42,7 +42,7 @@ chip = {
|
||||
'spi' : 4,
|
||||
'i2c' : 3,
|
||||
'adc' : 1,
|
||||
'dac' : 0,
|
||||
'dac' : 2,
|
||||
'saved_code' : {
|
||||
# code size 300000 = 0x493E0 starts at 0x0800 0000 ends at 0x0804 93E0
|
||||
# so we have some left room for Espruino firmware and no risk to clear it while saving
|
||||
|
||||
@ -72,7 +72,8 @@ devices = {
|
||||
board = {
|
||||
'bottom' : [ 'D28', 'D29', 'D30', 'D31'],
|
||||
'right' : [ 'GND', '3V', 'D2', 'D1' ],
|
||||
'right2' : [ 'D6','D7','D8','D11','D13','D14','D15','D16','D23','D24','D27' ],
|
||||
'left2' : [ 'D6','D7','D8','D11','D13','D14','D16','D23','D24','D27' ],
|
||||
'right2' : [ 'D15' ],
|
||||
'_notes' : {
|
||||
'D11' : "Capacitive sense. D12 is connected to this pin via a 1 MOhm resistor",
|
||||
'D29' : "If pulled up to 1 on startup, D28 and D29 become Serial1",
|
||||
@ -105,9 +106,9 @@ board["_css"] = """
|
||||
.pinD7 { position:absolute; left: 548px; top: 369px;}
|
||||
.pinD8 { position:absolute; left: 512px; top: 398px;}
|
||||
.pinD11 { position:absolute; left: 586px; top: 236px;}
|
||||
.pinD13 { position:absolute; left: 509px; top: 293px;}
|
||||
.pinD13 { position:absolute; left: 500px; top: 293px;}
|
||||
.pinD14 { position:absolute; left: 523px; top: 270px;}
|
||||
.pinD15 { position:absolute; left: 483px; top: 268px;}
|
||||
.pinD15 { position:absolute; right: -483px; top: 268px;}
|
||||
.pinD16 { position:absolute; left: 499px; top: 244px;}
|
||||
.pinD23 { position:absolute; left: 157px; top: 438px;}
|
||||
.pinD24 { position:absolute; left: 157px; top: 382px;}
|
||||
@ -121,23 +122,18 @@ def get_pins():
|
||||
pinutils.findpin(pins, "PD9", True)["functions"]["NFC1"]=0;
|
||||
pinutils.findpin(pins, "PD10", True)["functions"]["NFC2"]=0;
|
||||
pinutils.findpin(pins, "PD2", True)["functions"]["ADC1_IN0"]=0;
|
||||
pinutils.findpin(pins, "PD2", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD3", True)["functions"]["ADC1_IN1"]=0;
|
||||
pinutils.findpin(pins, "PD3", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD4", True)["functions"]["ADC1_IN2"]=0;
|
||||
pinutils.findpin(pins, "PD4", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD5", True)["functions"]["ADC1_IN3"]=0;
|
||||
pinutils.findpin(pins, "PD5", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD28", True)["functions"]["ADC1_IN4"]=0;
|
||||
pinutils.findpin(pins, "PD28", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD28", True)["functions"]["USART1_TX"]=0;
|
||||
pinutils.findpin(pins, "PD29", True)["functions"]["USART1_RX"]=0;
|
||||
pinutils.findpin(pins, "PD29", True)["functions"]["ADC1_IN5"]=0;
|
||||
pinutils.findpin(pins, "PD29", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD30", True)["functions"]["ADC1_IN6"]=0;
|
||||
pinutils.findpin(pins, "PD30", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD31", True)["functions"]["ADC1_IN7"]=0;
|
||||
pinutils.findpin(pins, "PD31", True)["functions"]["3.3"]=0;
|
||||
pinutils.findpin(pins, "PD31", True)["functions"]["ADC1_IN7"]=0;
|
||||
# everything is non-5v tolerant
|
||||
for pin in pins:
|
||||
pin["functions"]["3.3"]=0;
|
||||
|
||||
#The boot/reset button will function as a reset button in normal operation. Pin reset on PD21 needs to be enabled on the nRF52832 device for this to work.
|
||||
return pins
|
||||
|
||||
@ -101,7 +101,21 @@ void bleCompleteTaskFailAndUnLock(BleTask task, JsVar *data) {
|
||||
bleCompleteTask(task, false, data);
|
||||
jsvUnLock(data);
|
||||
}
|
||||
void bleSwitchTask(BleTask task) {
|
||||
bleTask = task;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------
|
||||
#ifdef NRF52
|
||||
void bleSetActiveBluetoothGattServer(JsVar *var) {
|
||||
jsvObjectSetChild(execInfo.hiddenRoot, BLE_NAME_GATT_SERVER, var);
|
||||
}
|
||||
|
||||
JsVar *bleGetActiveBluetoothGattServer() {
|
||||
return jsvObjectGetChild(execInfo.hiddenRoot, BLE_NAME_GATT_SERVER, 0);
|
||||
}
|
||||
#endif
|
||||
// ------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
@ -216,6 +230,40 @@ Called when an NFC field is detected
|
||||
}
|
||||
Called when an NFC field is no longer detected
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "event",
|
||||
"class" : "BluetoothDevice",
|
||||
"name" : "gattserverdisconnected",
|
||||
"ifdef" : "NRF52"
|
||||
}
|
||||
Called when the device gets disconnected.
|
||||
|
||||
To connect and then print `Disconnected` when the device is
|
||||
disconnected, just do the following:
|
||||
|
||||
```
|
||||
var gatt;
|
||||
var t = getTime();
|
||||
NRF.connect("aa:bb:cc:dd:ee:ff").then(function(gatt) {
|
||||
gatt.device.on('gattserverdisconnected', function(event) {
|
||||
console.log("Disconnected");
|
||||
});
|
||||
});
|
||||
```
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "event",
|
||||
"class" : "BluetoothRemoteGATTCharacteristic",
|
||||
"name" : "characteristicvaluechanged",
|
||||
"ifdef" : "NRF52"
|
||||
}
|
||||
Called when a characteristic's value changes, *after* `BluetoothRemoteGATTCharacteristic.startNotifications` has been called.
|
||||
See that for an example.
|
||||
|
||||
The first argument is of the form `{target : BluetoothRemoteGATTCharacteristic}`
|
||||
|
||||
`BluetoothRemoteGATTCharacteristic.value` will then contain the new value.
|
||||
*/
|
||||
|
||||
/*JSON{
|
||||
"type": "class",
|
||||
@ -535,6 +583,43 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
jsble_advertising_start();
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "setScanResponse",
|
||||
"generate" : "jswrap_nrf_bluetooth_setScanResponse",
|
||||
"params" : [
|
||||
["data","JsVar","The data to for the scan response"]
|
||||
]
|
||||
}
|
||||
|
||||
The raw scan response data should be supplied as an array. For example to return "Sample" for the device name:
|
||||
|
||||
```
|
||||
NRF.setScanResponse([0x07, // Length of Data
|
||||
0x09, // Param: Complete Local Name
|
||||
'S', 'a', 'm', 'p', 'l', 'e']);
|
||||
```
|
||||
*/
|
||||
void jswrap_nrf_bluetooth_setScanResponse(JsVar *data) {
|
||||
uint32_t err_code;
|
||||
|
||||
jsvObjectSetOrRemoveChild(execInfo.hiddenRoot, BLE_NAME_SCAN_RESPONSE_DATA, data);
|
||||
|
||||
if (jsvIsArray(data) || jsvIsArrayBuffer(data)) {
|
||||
JSV_GET_AS_CHAR_ARRAY(dPtr, dLen, data);
|
||||
if (!dPtr) {
|
||||
jsExceptionHere(JSET_TYPEERROR, "Unable to convert data argument to an array");
|
||||
return;
|
||||
}
|
||||
|
||||
err_code = sd_ble_gap_adv_data_set(NULL, 0, (uint8_t *)dPtr, dLen);
|
||||
jsble_check_error(err_code);
|
||||
} else if (!jsvIsUndefined(data)) {
|
||||
jsExceptionHere(JSET_TYPEERROR, "Expecting array-like object or undefined, got %t", data);
|
||||
}
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
@ -548,6 +633,9 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
|
||||
Change the services and characteristics Espruino advertises.
|
||||
|
||||
If you want to **change** the value of a characteristic, you need
|
||||
to use `NRF.updateServices()` instead
|
||||
|
||||
To expose some information on Characteristic `ABCD` on service `BCDE` you could do:
|
||||
|
||||
```
|
||||
@ -889,7 +977,7 @@ void jswrap_nrf_bluetooth_setScan_cb(JsVar *callback, JsVar *adv) {
|
||||
}
|
||||
} else if (field_type == BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE ||
|
||||
field_type == BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE) {
|
||||
JsVar *s = jsvVarPrintf("%04x", *(uint16_t*)&dPtr[i+2]);
|
||||
JsVar *s = jsvVarPrintf("%04x", UNALIGNED_UINT16(&dPtr[i+2]));
|
||||
jsvArrayPushAndUnLock(services, s);
|
||||
} else if (field_type == BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE ||
|
||||
field_type == BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE) {
|
||||
@ -1037,20 +1125,18 @@ void jswrap_nrf_bluetooth_findDevices(JsVar *callback, JsVar *timeout) {
|
||||
}
|
||||
|
||||
Start/stop listening for RSSI values on the currently active connection
|
||||
|
||||
RSSI is the 'Received Signal Strength Indication' in dBm
|
||||
(where This device is a peripheral and is being connected to by a 'central' device)
|
||||
|
||||
```
|
||||
// Start scanning
|
||||
NRF.setRSSIHandler(function(rssi) {
|
||||
console.log(rssi);
|
||||
console.log(rssi); // prints -85 (or similar)
|
||||
});
|
||||
// prints -85 (or similar)
|
||||
|
||||
// Stop Scanning
|
||||
NRF.setRSSIHandler();
|
||||
```
|
||||
|
||||
RSSI is the 'Received Signal Strength Indication' in dBm
|
||||
*/
|
||||
void jswrap_nrf_bluetooth_setRSSIHandler(JsVar *callback) {
|
||||
// set the callback event variable
|
||||
@ -1886,12 +1972,31 @@ NRF.connect(device_address).then(function(d) {
|
||||
});
|
||||
```
|
||||
|
||||
For example, to listen to the output of another Puck.js's Nordic
|
||||
Serial port service, you can use:
|
||||
|
||||
```
|
||||
var gatt;
|
||||
NRF.connect("pu:ck:js:ad:dr:es random").then(function(g) {
|
||||
gatt = g;
|
||||
return gatt.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
|
||||
}).then(function(service) {
|
||||
return service.getCharacteristic("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
|
||||
}).then(function(characteristic) {
|
||||
characteristic.on('characteristicvaluechanged', function(event) {
|
||||
console.log("RX: "+JSON.stringify(event.target.value.buffer));
|
||||
});
|
||||
return characteristic.startNotifications();
|
||||
}).then(function() {
|
||||
console.log("Done!");
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** This is only available on some devices
|
||||
*/
|
||||
JsVar *jswrap_nrf_BluetoothRemoteGATTCharacteristic_startNotifications(JsVar *characteristic) {
|
||||
#if 0 // CENTRAL_LINK_COUNT>0
|
||||
if (!bleNewTask(BLETASK_CHARACTERISTIC_NOTIFY, 0))
|
||||
return 0;
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
|
||||
// Set our characteristic's handle up in the list of handles to notify for
|
||||
// TODO: What happens when we close the connection and re-open another?
|
||||
uint16_t handle = (uint16_t)jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_value", 0));
|
||||
@ -1900,8 +2005,23 @@ JsVar *jswrap_nrf_BluetoothRemoteGATTCharacteristic_startNotifications(JsVar *ch
|
||||
jsvSetArrayItem(handles, handle, characteristic);
|
||||
jsvUnLock(handles);
|
||||
}
|
||||
JsVar *promise = jsvLockAgainSafe(blePromise);
|
||||
jsble_central_characteristicNotify(characteristic, true);
|
||||
|
||||
JsVar *promise;
|
||||
|
||||
// Check for existing cccd_handle
|
||||
uint16_t cccd = (uint16_t)jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic,"handle_cccd", 0));
|
||||
if ( !cccd ) {
|
||||
if (!bleNewTask(BLETASK_CHARACTERISTIC_DESC_AND_STARTNOTIFY, characteristic))
|
||||
return 0;
|
||||
promise = jsvLockAgainSafe(blePromise);
|
||||
jsble_central_characteristicDescDiscover(characteristic);
|
||||
}
|
||||
else {
|
||||
if (!bleNewTask(BLETASK_CHARACTERISTIC_NOTIFY, 0))
|
||||
return 0;
|
||||
promise = jsvLockAgainSafe(blePromise);
|
||||
jsble_central_characteristicNotify(characteristic, true);
|
||||
}
|
||||
return promise;
|
||||
#else
|
||||
jsExceptionHere(JSET_ERROR, "Unimplemented");
|
||||
@ -1914,12 +2034,12 @@ JsVar *jswrap_nrf_BluetoothRemoteGATTCharacteristic_startNotifications(JsVar *ch
|
||||
"class" : "BluetoothRemoteGATTCharacteristic",
|
||||
"name" : "stopNotifications",
|
||||
"generate" : "jswrap_nrf_BluetoothRemoteGATTCharacteristic_stopNotifications",
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) with data when notifications have been added" ]
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) with data when notifications have been removed" ]
|
||||
}
|
||||
**Note:** This is only available on some devices
|
||||
*/
|
||||
JsVar *jswrap_nrf_BluetoothRemoteGATTCharacteristic_stopNotifications(JsVar *characteristic) {
|
||||
#if 0 // CENTRAL_LINK_COUNT>0
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
// Remove our characteristic handle from the list of handles to notify for
|
||||
uint16_t handle = (uint16_t)jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_value", 0));
|
||||
JsVar *handles = jsvObjectGetChild(execInfo.hiddenRoot, "bleHdl", JSV_ARRAY);
|
||||
|
||||
@ -23,6 +23,7 @@ typedef enum {
|
||||
BLETASK_CHARACTERISTIC, ///< Find characteristics
|
||||
BLETASK_CHARACTERISTIC_WRITE, ///< Write to a characteristic
|
||||
BLETASK_CHARACTERISTIC_READ, ///< Read from a characteristic
|
||||
BLETASK_CHARACTERISTIC_DESC_AND_STARTNOTIFY, ///< Discover descriptors and start notifications
|
||||
BLETASK_CHARACTERISTIC_NOTIFY, ///< Setting whether notifications are on or off
|
||||
BLETASK_CENTRAL_END = BLETASK_CHARACTERISTIC_NOTIFY // ============= End of central tasks
|
||||
} BleTask;
|
||||
@ -38,6 +39,15 @@ void bleCompleteTaskSuccess(BleTask task, JsVar *data);
|
||||
void bleCompleteTaskSuccessAndUnLock(BleTask task, JsVar *data);
|
||||
void bleCompleteTaskFail(BleTask task, JsVar *data);
|
||||
void bleCompleteTaskFailAndUnLock(BleTask task, JsVar *data);
|
||||
void bleSwitchTask(BleTask task);
|
||||
|
||||
#ifdef NRF52
|
||||
// Set the currently active GATT server
|
||||
void bleSetActiveBluetoothGattServer(JsVar *var);
|
||||
// Get the currently active GATT server (the return value needs unlocking)
|
||||
JsVar *bleGetActiveBluetoothGattServer();
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
void jswrap_nrf_init();
|
||||
bool jswrap_nrf_idle();
|
||||
@ -53,6 +63,7 @@ JsVar *jswrap_nrf_bluetooth_getAddress();
|
||||
|
||||
JsVarFloat jswrap_nrf_bluetooth_getBattery();
|
||||
void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options);
|
||||
void jswrap_nrf_bluetooth_setScanResponse(JsVar *data);
|
||||
void jswrap_nrf_bluetooth_setServices(JsVar *data, JsVar *options);
|
||||
void jswrap_nrf_bluetooth_updateServices(JsVar *data);
|
||||
void jswrap_nrf_bluetooth_setScan(JsVar *callback);
|
||||
|
||||
1590
libs/network/esp32/jswrap_esp32_network.c
Normal file
1590
libs/network/esp32/jswrap_esp32_network.c
Normal file
File diff suppressed because it is too large
Load Diff
36
libs/network/esp32/jswrap_esp32_network.h
Normal file
36
libs/network/esp32/jswrap_esp32_network.h
Normal file
@ -0,0 +1,36 @@
|
||||
void jswrap_ESP32_wifi_soft_init();
|
||||
void jswrap_ESP32_wifi_disconnect(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_stopAP(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_connect(
|
||||
JsVar *jsSsid,
|
||||
JsVar *jsOptions,
|
||||
JsVar *jsCallback
|
||||
);
|
||||
void jswrap_ESP32_wifi_scan(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_startAP(
|
||||
JsVar *jsSsid, //!< The network SSID that we will use to listen as.
|
||||
JsVar *jsOptions, //!< Configuration options.
|
||||
JsVar *jsCallback //!< A callback to be invoked when completed.
|
||||
);
|
||||
JsVar *jswrap_ESP32_wifi_getStatus(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_setConfig(JsVar *jsSettings);
|
||||
JsVar *jswrap_ESP32_wifi_getDetails(JsVar *jsCallback);
|
||||
JsVar *jswrap_ESP32_wifi_getAPDetails(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_save(JsVar *what);
|
||||
void jswrap_ESP32_wifi_restore(void);
|
||||
JsVar *jswrap_ESP32_wifi_getIP(JsVar *jsCallback);
|
||||
JsVar *jswrap_ESP32_wifi_getAPIP(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_getHostByName(
|
||||
JsVar *jsHostname,
|
||||
JsVar *jsCallback
|
||||
);
|
||||
JsVar *jswrap_ESP32_wifi_getHostname(JsVar *jsCallback);
|
||||
void jswrap_ESP32_wifi_setHostname(
|
||||
JsVar *jsHostname //!< The hostname to set for device.
|
||||
);
|
||||
void jswrap_ESP32_ping(
|
||||
JsVar *ipAddr, //!< A string or integer representation of an IP address.
|
||||
JsVar *pingCallback //!< Optional callback function.
|
||||
);
|
||||
|
||||
void esp32_wifi_init();
|
||||
232
libs/network/esp32/network_esp32.c
Normal file
232
libs/network/esp32/network_esp32.c
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Implementation of JsNetwork for ESP32 - cloned from linux
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "network_esp32.h"
|
||||
|
||||
#include "network.h"
|
||||
#include <string.h> // for memset
|
||||
|
||||
#define INVALID_SOCKET ((SOCKET)(-1))
|
||||
#define SOCKET_ERROR (-1)
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#ifndef ESP_PLATFORM
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct sockaddr_in sockaddr_in;
|
||||
typedef int SOCKET;
|
||||
#endif
|
||||
|
||||
#define closesocket(SOCK) close(SOCK)
|
||||
|
||||
|
||||
/// Get an IP address from a name. Sets out_ip_addr to 0 on failure
|
||||
void net_esp32_gethostbyname(JsNetwork *net, char * hostName, uint32_t* out_ip_addr) {
|
||||
NOT_USED(net);
|
||||
struct hostent * host_addr_p = gethostbyname(hostName);
|
||||
if (host_addr_p)
|
||||
*out_ip_addr = *(uint32_t*)*host_addr_p->h_addr_list;
|
||||
}
|
||||
|
||||
/// Called on idle. Do any checks required for this device
|
||||
void net_esp32_idle(JsNetwork *net) {
|
||||
NOT_USED(net);
|
||||
}
|
||||
|
||||
/// Call just before returning to idle loop. This checks for errors and tries to recover. Returns true if no errors.
|
||||
bool net_esp32_checkError(JsNetwork *net) {
|
||||
NOT_USED(net);
|
||||
bool hadErrors = false;
|
||||
return hadErrors;
|
||||
}
|
||||
|
||||
/// if host=0, creates a server otherwise creates a client (and automatically connects). Returns >=0 on success
|
||||
int net_esp32_createsocket(JsNetwork *net, uint32_t host, unsigned short port) {
|
||||
NOT_USED(net);
|
||||
int sckt = -1;
|
||||
if (host!=0) { // ------------------------------------------------- host (=client)
|
||||
sockaddr_in sin;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons( port );
|
||||
|
||||
sckt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sckt<0) return sckt; // error
|
||||
|
||||
// turn on non-blocking mode
|
||||
#ifdef WIN_OS
|
||||
u_long n = 1;
|
||||
ioctlsocket(sckt,FIONBIO,&n);
|
||||
#endif
|
||||
|
||||
sin.sin_addr.s_addr = (in_addr_t)host;
|
||||
|
||||
int res = connect(sckt,(struct sockaddr *)&sin, sizeof(sockaddr_in) );
|
||||
|
||||
if (res == SOCKET_ERROR) {
|
||||
#ifdef WIN_OS
|
||||
int err = WSAGetLastError();
|
||||
#else
|
||||
int err = errno;
|
||||
#endif
|
||||
if (err != EINPROGRESS &&
|
||||
err != EWOULDBLOCK) {
|
||||
jsError("Connect failed (err %d)\n", err );
|
||||
closesocket(sckt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // ------------------------------------------------- no host (=server)
|
||||
|
||||
sckt = socket(AF_INET, // Go over TCP/IP
|
||||
SOCK_STREAM, // This is a stream-oriented socket
|
||||
IPPROTO_TCP); // Use TCP rather than UDP
|
||||
if (sckt == INVALID_SOCKET) {
|
||||
jsError("Socket creation failed");
|
||||
return 0;
|
||||
}
|
||||
int optval = 1;
|
||||
if (setsockopt(sckt,SOL_SOCKET,SO_REUSEADDR,(const char *)&optval,sizeof(optval)) < 0)
|
||||
jsWarn("setsockopt(SO_REUSADDR) failed\n");
|
||||
|
||||
int nret;
|
||||
sockaddr_in serverInfo;
|
||||
memset(&serverInfo, 0, sizeof(serverInfo));
|
||||
serverInfo.sin_family = AF_INET;
|
||||
//serverInfo.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // allow only LOCAL clients to connect
|
||||
serverInfo.sin_addr.s_addr = INADDR_ANY; // allow anyone to connect
|
||||
serverInfo.sin_port = (unsigned short)htons((unsigned short)port); // port
|
||||
nret = bind(sckt, (struct sockaddr*)&serverInfo, sizeof(serverInfo));
|
||||
if (nret == SOCKET_ERROR) {
|
||||
jsError("Socket bind failed");
|
||||
closesocket(sckt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Make the socket listen
|
||||
nret = listen(sckt, 10); // 10 connections (but this ignored on CC30000)
|
||||
if (nret == SOCKET_ERROR) {
|
||||
jsError("Socket listen failed, host:%d, port:%d\n",(int)host,(int)port);
|
||||
closesocket(sckt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
// disable SIGPIPE
|
||||
int optval = 1;
|
||||
if (setsockopt(sckt,SOL_SOCKET,SO_NOSIGPIPE,(const char *)&optval,sizeof(optval))<0)
|
||||
jsWarn("setsockopt(SO_NOSIGPIPE) failed\n");
|
||||
#endif
|
||||
|
||||
return sckt;
|
||||
}
|
||||
|
||||
/// destroys the given socket
|
||||
void net_esp32_closesocket(JsNetwork *net, int sckt) {
|
||||
NOT_USED(net);
|
||||
closesocket(sckt);
|
||||
}
|
||||
|
||||
/// If the given server socket can accept a connection, return it (or return < 0)
|
||||
int net_esp32_accept(JsNetwork *net, int sckt) {
|
||||
NOT_USED(net);
|
||||
// TODO: look for unreffed servers?
|
||||
fd_set s;
|
||||
FD_ZERO(&s);
|
||||
FD_SET(sckt,&s);
|
||||
// check for waiting clients
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
int n = select(sckt+1,&s,NULL,NULL,&timeout);
|
||||
if (n>0) {
|
||||
// we have a client waiting to connect... try to connect and see what happens
|
||||
int theClient = accept(sckt,0,0);
|
||||
return theClient;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Receive data if possible. returns nBytes on success, 0 on no data, or -1 on failure
|
||||
int net_esp32_recv(JsNetwork *net, int sckt, void *buf, size_t len) {
|
||||
NOT_USED(net);
|
||||
int num = 0;
|
||||
fd_set s;
|
||||
FD_ZERO(&s);
|
||||
FD_SET(sckt,&s);
|
||||
// check for waiting clients
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
int n = select(sckt+1,&s,NULL,NULL,&timeout);
|
||||
if (n==SOCKET_ERROR) {
|
||||
// we probably disconnected
|
||||
return -1;
|
||||
} else if (n>0) {
|
||||
// receive data
|
||||
num = (int)recv(sckt,buf,len,0);
|
||||
if (num==0) num=-1; // select says data, but recv says 0 means connection is closed
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/// Send data if possible. returns nBytes on success, 0 on no data, or -1 on failure
|
||||
int net_esp32_send(JsNetwork *net, int sckt, const void *buf, size_t len) {
|
||||
NOT_USED(net);
|
||||
fd_set writefds;
|
||||
FD_ZERO(&writefds);
|
||||
FD_SET(sckt, &writefds);
|
||||
struct timeval time;
|
||||
time.tv_sec = 0;
|
||||
time.tv_usec = 0;
|
||||
int n = select(sckt+1, 0, &writefds, 0, &time);
|
||||
if (n==SOCKET_ERROR ) {
|
||||
// we probably disconnected so just get rid of this
|
||||
return -1;
|
||||
} else if (FD_ISSET(sckt, &writefds)) {
|
||||
int flags = 0;
|
||||
#if !defined(SO_NOSIGPIPE) && defined(MSG_NOSIGNAL)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
n = (int)send(sckt, buf, len, flags);
|
||||
return n;
|
||||
} else
|
||||
return 0; // just not ready
|
||||
}
|
||||
|
||||
void netSetCallbacks_esp32(JsNetwork *net) {
|
||||
net->idle = net_esp32_idle;
|
||||
net->checkError = net_esp32_checkError;
|
||||
net->createsocket = net_esp32_createsocket;
|
||||
net->closesocket = net_esp32_closesocket;
|
||||
net->accept = net_esp32_accept;
|
||||
net->gethostbyname = net_esp32_gethostbyname;
|
||||
net->recv = net_esp32_recv;
|
||||
net->send = net_esp32_send;
|
||||
net->chunkSize = 536;
|
||||
}
|
||||
16
libs/network/esp32/network_esp32.h
Normal file
16
libs/network/esp32/network_esp32.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Implementation of JsNetwork for Linux
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "network.h"
|
||||
|
||||
void netSetCallbacks_esp32(JsNetwork *net);
|
||||
@ -24,15 +24,18 @@
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#ifndef ESP_PLATFORM
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <resolv.h>
|
||||
|
||||
typedef struct sockaddr_in sockaddr_in;
|
||||
typedef int SOCKET;
|
||||
#endif
|
||||
|
||||
@ -28,6 +28,9 @@
|
||||
#if defined(USE_ESP8266)
|
||||
#include "network_esp8266.h"
|
||||
#endif
|
||||
#if defined(USE_ESP32)
|
||||
#include "network_esp32.h"
|
||||
#endif
|
||||
#if defined(LINUX)
|
||||
#include "network_linux.h"
|
||||
#endif
|
||||
@ -235,6 +238,9 @@ bool networkGetFromVar(JsNetwork *net) {
|
||||
#if defined(USE_ESP8266)
|
||||
case JSNETWORKTYPE_ESP8266_BOARD : netSetCallbacks_esp8266_board(net); break;
|
||||
#endif
|
||||
#if defined(USE_ESP32)
|
||||
case JSNETWORKTYPE_ESP32 : netSetCallbacks_esp32(net); break;
|
||||
#endif
|
||||
#if defined(LINUX)
|
||||
case JSNETWORKTYPE_SOCKET : netSetCallbacks_linux(net); break;
|
||||
#endif
|
||||
|
||||
@ -37,6 +37,7 @@ typedef enum {
|
||||
JSNETWORKTYPE_W5500, ///< WIZnet W5500 support
|
||||
JSNETWORKTYPE_JS, ///< JavaScript network type
|
||||
JSNETWORKTYPE_ESP8266_BOARD, ///< Espressif ESP8266 board support
|
||||
JSNETWORKTYPE_ESP32 /// < Espressif ESP32 board support
|
||||
} JsNetworkType;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
#if defined(ESP8266)
|
||||
extern int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2)));
|
||||
#define printf os_printf_plus
|
||||
#elif defined(ESP32) && !defined(RELEASE)
|
||||
#define printf jsWarn
|
||||
//#elif defined(LINUX)
|
||||
//#define printf printf
|
||||
#else
|
||||
|
||||
2
scripts/build_platform_config.py
Executable file → Normal file
2
scripts/build_platform_config.py
Executable file → Normal file
@ -209,6 +209,8 @@ elif board.chip["family"]=="AVR":
|
||||
board.chip["class"]="AVR"
|
||||
elif board.chip["family"]=="ESP8266":
|
||||
board.chip["class"]="ESP8266"
|
||||
elif board.chip["family"]=="ESP32":
|
||||
board.chip["class"]="ESP32"
|
||||
else:
|
||||
die('Unknown chip family '+board.chip["family"])
|
||||
|
||||
|
||||
@ -4,3 +4,16 @@
|
||||
^\./libs/fat_sd
|
||||
^\./libs/math
|
||||
^\./tmp
|
||||
^\./gen
|
||||
^\./build
|
||||
^\./xtensa-lx106-elf
|
||||
^\./esp_iot_sdk_v2.0.0.p1/
|
||||
^\./node_modules
|
||||
^\./zipcontents
|
||||
^\./libs/filesystem/fat_sd
|
||||
^\./libs/hashlib
|
||||
^\./libs/network/wiznet/.*/
|
||||
^\./libs/network/cc3000
|
||||
^\./libs/compression/heatshrink
|
||||
^\./libs/crypto/mbedtls
|
||||
^\./.*\.js
|
||||
|
||||
@ -3,4 +3,12 @@
|
||||
cd `dirname $0`
|
||||
cd ..
|
||||
|
||||
find . | grep -f scripts/count_lines.include | grep -v -f scripts/count_lines.exclude
|
||||
|
||||
echo "Total lines"
|
||||
find . | grep -f scripts/count_lines.include | grep -v -f scripts/count_lines.exclude | xargs cat | wc -l
|
||||
|
||||
#Can also count by lines written
|
||||
#find . | grep -f scripts/count_lines.include | grep -v -f scripts/count_lines.exclude | xargs -I{} git blame {} | sed -ne "s/[^(]*(\([A-Za-z0-9]*\).*/\1/p" > blames
|
||||
#sort blames | uniq -c | sort -n
|
||||
|
||||
|
||||
@ -421,4 +421,7 @@ unsigned int jshSetSystemClock(JsVar *options);
|
||||
if (timeout<=0 || jspIsInterrupted()) { jsExceptionHere(JSET_INTERNALERROR, "Timeout on "REASON); } \
|
||||
}
|
||||
|
||||
/** Send the given RGB pixel data out to neopixel/WS2811/APA104/etc */
|
||||
bool jshNeopixelWrite(Pin pin, unsigned char *rgbData, size_t rgbSize);
|
||||
|
||||
#endif /* JSHARDWARE_H_ */
|
||||
|
||||
@ -37,6 +37,10 @@ extern void jshPrintBanner(void); // prints a debugging banner while we're in be
|
||||
extern void jshSoftInit(void); // re-inits wifi after a soft-reset
|
||||
#endif
|
||||
|
||||
#ifdef ESP32
|
||||
extern void jshSoftInit(void);
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
typedef enum {
|
||||
IS_NONE,
|
||||
@ -777,6 +781,9 @@ void jsiSemiInit(bool autoLoad) {
|
||||
#ifdef ESP8266
|
||||
jshSoftInit();
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
jshSoftInit();
|
||||
#endif
|
||||
|
||||
if (jsiEcho()) { // intentionally not using jsiShowInputLine()
|
||||
if (!loadFlash) {
|
||||
|
||||
@ -1553,7 +1553,7 @@ NO_INLINE JsVar *jspeFactor() {
|
||||
return jspeFactorTypeOf();
|
||||
} else if (lex->tk==LEX_R_VOID) {
|
||||
JSP_ASSERT_MATCH(LEX_R_VOID);
|
||||
jsvUnLock(jspeFactor());
|
||||
jsvUnLock(jspeUnaryExpression());
|
||||
return 0;
|
||||
}
|
||||
JSP_MATCH(LEX_EOF);
|
||||
|
||||
21
src/jspin.c
21
src/jspin.c
@ -238,6 +238,27 @@ JshPinFunction jshGetPinFunctionFromDevice(IOEventFlags device) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a jshPinFunction to an event type flag
|
||||
IOEventFlags jshGetFromDevicePinFunction(JshPinFunction func) {
|
||||
switch (func & JSH_MASK_TYPE) {
|
||||
case JSH_USART1 : return EV_SERIAL1;
|
||||
case JSH_USART2 : return EV_SERIAL2;
|
||||
case JSH_USART3 : return EV_SERIAL3;
|
||||
case JSH_USART4 : return EV_SERIAL4;
|
||||
case JSH_USART5 : return EV_SERIAL5;
|
||||
case JSH_USART6 : return EV_SERIAL6;
|
||||
|
||||
case JSH_SPI1 : return EV_SPI1;
|
||||
case JSH_SPI2 : return EV_SPI2;
|
||||
case JSH_SPI3 : return EV_SPI3;
|
||||
|
||||
case JSH_I2C1 : return EV_I2C1;
|
||||
case JSH_I2C2 : return EV_I2C2;
|
||||
case JSH_I2C3 : return EV_I2C3;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Try and find a specific type of function for the given pin. Can be given an invalid pin and will return 0. */
|
||||
JshPinFunction NO_INLINE jshGetPinFunctionForPin(Pin pin, JshPinFunction functionType) {
|
||||
if (!jshIsPinValid(pin)) return 0;
|
||||
|
||||
@ -180,8 +180,7 @@ typedef enum {
|
||||
(((F)&JSH_MASK_TYPE)>=JSH_TIMER1) && \
|
||||
(((F)&JSH_MASK_TYPE)<=JSH_TIMER18))
|
||||
#define JSH_PINFUNCTION_IS_DAC(F) ( \
|
||||
(((F)&JSH_MASK_TYPE)==JSH_DAC) || \
|
||||
0 )
|
||||
(((F)&JSH_MASK_TYPE)==JSH_DAC))
|
||||
#define JSH_PINFUNCTION_IS_USART(F) ( \
|
||||
(((F)&JSH_MASK_TYPE)>=JSH_USART1) && \
|
||||
(((F)&JSH_MASK_TYPE)<=JSH_USART6))
|
||||
@ -217,6 +216,8 @@ void jshPinOutput(Pin pin, bool value);
|
||||
|
||||
// Convert an event type flag into a jshPinFunction for an actual hardware device
|
||||
JshPinFunction jshGetPinFunctionFromDevice(IOEventFlags device);
|
||||
// Convert a jshPinFunction to an event type flag
|
||||
IOEventFlags jshGetFromDevicePinFunction(JshPinFunction func);
|
||||
|
||||
/** Try and find a specific type of function for the given pin. Can be given an invalid pin and will return 0. */
|
||||
JshPinFunction NO_INLINE jshGetPinFunctionForPin(Pin pin, JshPinFunction functionType);
|
||||
|
||||
@ -326,6 +326,12 @@ typedef int64_t JsSysTime;
|
||||
#define NIBBLEFIELD_CLEAR(BITFIELD) memset(BITFIELD, 0, sizeof(BITFIELD)) ///< Clear all elements
|
||||
*/
|
||||
|
||||
#if defined(NRF51)
|
||||
// Cortex-M0 does not support unaligned reads
|
||||
#define UNALIGNED_UINT16(addr) ((((uint16_t)*((uint8_t*)(addr)+1)) << 8) | (*(uint8_t*)(addr)))
|
||||
#else
|
||||
#define UNALIGNED_UINT16(addr) (*(uint16_t*)addr)
|
||||
#endif
|
||||
|
||||
bool isWhitespace(char ch);
|
||||
bool isNumeric(char ch);
|
||||
|
||||
11
src/jsvar.c
11
src/jsvar.c
@ -3484,6 +3484,17 @@ JsVar *jsvNewTypedArray(JsVarDataArrayBufferViewType type, JsVarInt length) {
|
||||
return array;
|
||||
}
|
||||
|
||||
JsVar *jsvNewTypedArrayWithData(JsVarDataArrayBufferViewType type, JsVarInt length, unsigned char *data) {
|
||||
JsVar *buf = jsvNewTypedArray(type, length);
|
||||
if (!buf) return 0;
|
||||
JsVarInt byteLength = JSV_ARRAYBUFFER_GET_SIZE(type) * length;
|
||||
JsVar *arrayBufferData = jsvGetArrayBufferBackingString(buf);
|
||||
if (arrayBufferData)
|
||||
jsvSetString(arrayBufferData, (char *)data, byteLength);
|
||||
jsvUnLock(arrayBufferData);
|
||||
return buf;
|
||||
}
|
||||
|
||||
JsVar *jsvNewArrayBufferWithPtr(unsigned int length, char **ptr) {
|
||||
assert(ptr);
|
||||
*ptr=0;
|
||||
|
||||
@ -730,6 +730,9 @@ bool jsvReadConfigObject(JsVar *object, jsvConfigObject *configs, int nConfigs);
|
||||
/// Create a new typed array of the given type and length
|
||||
JsVar *jsvNewTypedArray(JsVarDataArrayBufferViewType type, JsVarInt length);
|
||||
|
||||
/// Create a new typed array of the given type and length (in elements), and fill it with the given data
|
||||
JsVar *jsvNewTypedArrayWithData(JsVarDataArrayBufferViewType type, JsVarInt length, unsigned char *data);
|
||||
|
||||
/** Create a new arraybuffer of the given type and length, also return a pointer
|
||||
* to the contiguous memory area containing it. Returns 0 if it was unable to
|
||||
* allocate it. */
|
||||
|
||||
@ -470,10 +470,10 @@ JsVar* jsvArrayBufferIteratorGetIndex(JsvArrayBufferIterator *it) {
|
||||
return jsvNewFromInteger((JsVarInt)it->index);
|
||||
}
|
||||
|
||||
bool jsvArrayBufferIteratorHasElement(JsvArrayBufferIterator *it) {
|
||||
bool jsvArrayBufferIteratorHasElement(JsvArrayBufferIterator *it) {
|
||||
if (it->type == ARRAYBUFFERVIEW_UNDEFINED) return false;
|
||||
if (it->hasAccessedElement) return true;
|
||||
return it->byteOffset <= (it->byteLength-JSV_ARRAYBUFFER_GET_SIZE(it->type));
|
||||
return (it->byteOffset+JSV_ARRAYBUFFER_GET_SIZE(it->type)) <= it->byteLength;
|
||||
}
|
||||
|
||||
void jsvArrayBufferIteratorNext(JsvArrayBufferIterator *it) {
|
||||
@ -595,4 +595,3 @@ JsvIterator jsvIteratorClone(JsvIterator *it) {
|
||||
}
|
||||
return newit;
|
||||
}
|
||||
|
||||
|
||||
@ -1177,6 +1177,48 @@ void jswrap_espruino_lockConsole() {
|
||||
jsvUnLock(pwd);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "E",
|
||||
"name" : "neopixelWrite",
|
||||
"generate" : "jswrap_E_neopixelWrite",
|
||||
"params" : [
|
||||
["pin", "pin", "Pin for output signal."],
|
||||
["arrayOfData", "JsVar", "Array of RGB LED data bytes"]
|
||||
]
|
||||
}
|
||||
Write to NeoPixel/WS281x/APA10x-style LEDs attached to the given pin
|
||||
|
||||
Different types of LED have the data in different orders - so don't
|
||||
be surprised by RGB or BGR orderings!
|
||||
|
||||
**Note:** Espruino devices tend to have 3.3v IO, while WS2812/etc run
|
||||
off of 5v. Many WS2812 will only register a logic '1' at 70%
|
||||
of their input voltage - so if powering them off 5v you will not
|
||||
be able to send them data reliably. You can work around this by
|
||||
powering the LEDs off a lower voltage (for example 3.7v from a LiPo
|
||||
battery), or can put the output into the `af_opendrain` state and use
|
||||
a pullup resistor to 5v on STM32 based boards (nRF52 are not 5v tolerant
|
||||
so you can't do this).
|
||||
*/
|
||||
void jswrap_E_neopixelWrite(Pin pin, JsVar *jsArrayOfData) {
|
||||
JSV_GET_AS_CHAR_ARRAY(rgbData, rgbSize, jsArrayOfData);
|
||||
if (!rgbData) {
|
||||
jsExceptionHere(JSET_ERROR, "Couldn't convert %t to data to send to LEDs", jsArrayOfData);
|
||||
return;
|
||||
}
|
||||
if (rgbSize == 0) {
|
||||
jsExceptionHere(JSET_ERROR, "Data must be a non empty array.");
|
||||
return;
|
||||
}
|
||||
if (rgbSize % 3 != 0) {
|
||||
jsExceptionHere(JSET_ERROR, "Data length must be a multiple of 3 (RGB).");
|
||||
return;
|
||||
}
|
||||
|
||||
jshNeopixelWrite(pin, (unsigned char *)rgbData, rgbSize);
|
||||
}
|
||||
|
||||
// ----------------------------------------- USB Specific Stuff
|
||||
|
||||
#ifdef USE_USB_HID
|
||||
|
||||
@ -44,6 +44,7 @@ JsVar *jswrap_e_dumpStr();
|
||||
JsVarInt jswrap_espruino_HSBtoRGB(JsVarFloat hue, JsVarFloat sat, JsVarFloat bri);
|
||||
void jswrap_espruino_setPassword(JsVar *pwd);
|
||||
void jswrap_espruino_lockConsole();
|
||||
void jswrap_E_neopixelWrite(Pin pin, JsVar *jsArrayOfData);
|
||||
|
||||
void jswrap_espruino_setUSBHID(JsVar *arr);
|
||||
bool jswrap_espruino_sendUSBHID(JsVar *arr);
|
||||
|
||||
@ -423,7 +423,8 @@ void jsfSaveToFlash(JsvSaveFlashFlags flags, JsVar *bootCode) {
|
||||
}
|
||||
endOfData = cbData[1];
|
||||
// make sure we write everything in buffer
|
||||
for(int i=0;i<FLASH_UNITARY_WRITE_SIZE;i++)
|
||||
int i;
|
||||
for(i=0;i<FLASH_UNITARY_WRITE_SIZE;i++)
|
||||
jsfSaveToFlash_writecb(0,cbData);
|
||||
|
||||
writtenBytes = endOfData - FLASH_SAVED_CODE_START;
|
||||
|
||||
@ -420,7 +420,7 @@
|
||||
// <e> I2S_ENABLED - nrf_drv_i2s - I2S peripheral driver
|
||||
//==========================================================
|
||||
#ifndef I2S_ENABLED
|
||||
#define I2S_ENABLED 0
|
||||
#define I2S_ENABLED 1
|
||||
#endif
|
||||
#if I2S_ENABLED
|
||||
// <o> I2S_CONFIG_SCK_PIN - SCK pin <0-31>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
|
||||
|
||||
#define HID_IN_EP 0x81
|
||||
#define HID_INTERFACE_NUMBER 0
|
||||
#define HID_INTERFACE_NUMBER 2
|
||||
#endif
|
||||
|
||||
extern USBD_HandleTypeDef hUsbDeviceFS;
|
||||
@ -75,7 +75,7 @@ __ALIGN_BEGIN static const uint8_t USBD_CDC_HID_DeviceQualifierDesc[USB_LEN_DEV_
|
||||
* No HID
|
||||
* CDC on Interfaces 0 and 1
|
||||
*/
|
||||
#define USBD_CDC_CFGDESC_SIZE 67
|
||||
#define USBD_CDC_CFGDESC_SIZE (67+8)
|
||||
const __ALIGN_BEGIN uint8_t USBD_CDC_CfgDesc[USBD_CDC_CFGDESC_SIZE] __ALIGN_END =
|
||||
{
|
||||
/*Configuration Descriptor*/
|
||||
@ -88,6 +88,16 @@ const __ALIGN_BEGIN uint8_t USBD_CDC_CfgDesc[USBD_CDC_CFGDESC_SIZE] __ALIGN_END
|
||||
0xC0, /* bmAttributes: self powered */
|
||||
0x32, /* MaxPower 0 mA */
|
||||
|
||||
/* Interface Association Descriptor */
|
||||
0x08, /* bLength: IAD descriptor size */
|
||||
0x0B, /* bDescriptorType: IAD */
|
||||
0x00, /* bFirstInterface: Number if first interface for grouping */
|
||||
0x02, /* bInterfaceCount: Interfaces count for grouping */
|
||||
0x02, /* bFunctionClass: The same as bInterfaceClass below */
|
||||
0x02, /* bFunctionSubClass: The same as bInterfaceSubClass below */
|
||||
0x01, /* bFunctionProtocol: The same as bInterfaceProtocol below */
|
||||
0x00, /* iFunction */
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/*CDC Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
@ -175,8 +185,8 @@ const __ALIGN_BEGIN uint8_t USBD_CDC_CfgDesc[USBD_CDC_CFGDESC_SIZE] __ALIGN_END
|
||||
* HID on Interface 0
|
||||
* CDC on Interfaces 1 and 2
|
||||
*/
|
||||
#define USBD_CDC_HID_CFGDESC_SIZE (67+25)
|
||||
#define USBD_CDC_HID_CFGDESC_REPORT_SIZE_IDX 25
|
||||
#define USBD_CDC_HID_CFGDESC_SIZE (67+25+8)
|
||||
#define USBD_CDC_HID_CFGDESC_REPORT_SIZE_IDX 91
|
||||
// NOT CONST - descriptor size needs updating as this is sent out
|
||||
__ALIGN_BEGIN uint8_t USBD_CDC_HID_CfgDesc[USBD_CDC_HID_CFGDESC_SIZE] __ALIGN_END =
|
||||
{
|
||||
@ -190,6 +200,95 @@ __ALIGN_BEGIN uint8_t USBD_CDC_HID_CfgDesc[USBD_CDC_HID_CFGDESC_SIZE] __ALIGN_EN
|
||||
0xC0, /* bmAttributes: self powered */
|
||||
0x32, /* MaxPower 0 mA */
|
||||
|
||||
/* Interface Association Descriptor */
|
||||
0x08, /* bLength: IAD descriptor size */
|
||||
0x0B, /* bDescriptorType: IAD */
|
||||
0x00, /* bFirstInterface: Number if first interface for grouping */
|
||||
0x02, /* bInterfaceCount: Interfaces count for grouping */
|
||||
0x02, /* bFunctionClass: The same as bInterfaceClass below */
|
||||
0x02, /* bFunctionSubClass: The same as bInterfaceSubClass below */
|
||||
0x01, /* bFunctionProtocol: The same as bInterfaceProtocol below */
|
||||
0x00, /* iFunction */
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/*CDC Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
1, /* bDataInterface */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0, /* bMasterInterface: Communication class interface */
|
||||
1, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SIZE),
|
||||
0x10, /* bInterval: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
|
||||
1, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_FS_OUT_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_FS_OUT_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_FS_IN_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_FS_IN_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 9 */
|
||||
0x09, /*bLength: Interface Descriptor size*/
|
||||
@ -219,85 +318,6 @@ __ALIGN_BEGIN uint8_t USBD_CDC_HID_CfgDesc[USBD_CDC_HID_CFGDESC_SIZE] __ALIGN_EN
|
||||
0x03, /*bmAttributes: Interrupt endpoint*/
|
||||
HID_DATA_IN_PACKET_SIZE,0x00, /*wMaxPacketSize: 4 Byte max */
|
||||
HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/*CDC Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
1, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
2, /* bDataInterface */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
1, /* bMasterInterface: Communication class interface */
|
||||
2, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SIZE),
|
||||
0x10, /* bInterval: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
|
||||
2, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_FS_OUT_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_FS_OUT_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_FS_IN_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_FS_IN_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
} ;
|
||||
|
||||
#define USB_HID_DESC_SIZ 9
|
||||
@ -839,5 +859,3 @@ uint8_t USBD_HID_SendReport (uint8_t *report, unsigned int len)
|
||||
int USB_IsConnected() {
|
||||
return hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
*/
|
||||
|
||||
/*---------- -----------*/
|
||||
#define USBD_MAX_NUM_INTERFACES 1
|
||||
#define USBD_MAX_NUM_INTERFACES 2
|
||||
/*---------- -----------*/
|
||||
#define USBD_MAX_NUM_CONFIGURATION 1
|
||||
/*---------- -----------*/
|
||||
@ -78,8 +78,8 @@
|
||||
|
||||
/****************************************/
|
||||
/* #define for FS and HS identification */
|
||||
#define DEVICE_FS 0
|
||||
#define DEVICE_HS 1
|
||||
#define DEVICE_FS 0
|
||||
#define DEVICE_HS 1
|
||||
|
||||
/** @defgroup USBD_Exported_Macros
|
||||
* @{
|
||||
|
||||
@ -128,9 +128,9 @@ __ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
|
||||
0x00, /* bcdUSB */
|
||||
#endif
|
||||
0x02,
|
||||
0x02, /*bDeviceClass - CDC */
|
||||
0x00, /*bDeviceSubClass*/
|
||||
0x00, /*bDeviceProtocol*/
|
||||
0xEF, /*bDeviceClass - CDC */
|
||||
0x02, /*bDeviceSubClass*/
|
||||
0x01, /*bDeviceProtocol*/
|
||||
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
|
||||
LOBYTE(USBD_VID), /*idVendor*/
|
||||
HIBYTE(USBD_VID), /*idVendor*/
|
||||
|
||||
@ -1033,3 +1033,8 @@ unsigned int jshGetRandomNumber() {
|
||||
unsigned int jshSetSystemClock(JsVar *options) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool jshNeopixelWrite(Pin pin, unsigned char *rgbData, size_t rgbSize) {
|
||||
jsExceptionHere(JSET_ERROR, "Neopixel writing not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
18
targets/esp32/README_flash.txt
Normal file
18
targets/esp32/README_flash.txt
Normal file
@ -0,0 +1,18 @@
|
||||
How to flash Espruino ESP32
|
||||
===========================
|
||||
|
||||
*** To flash an ESP32 using the serial port use:
|
||||
python $(ESP_IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
--port "/dev/ttyUSB0" \
|
||||
--baud 921600 \
|
||||
write_flash \
|
||||
-z \
|
||||
--flash_mode "dio" \
|
||||
--flash_freq "40m" \
|
||||
0x1000 bootloader.bin \
|
||||
0x10000 espruino_esp32.bin \
|
||||
0x8000 partitions_singleapp.bin
|
||||
|
||||
On windows, its an option to use flash tools from espressif found here:
|
||||
http://espressif.com/sites/default/files/tools/flash_download_tools_v3.4.4.zip
|
||||
15
targets/esp32/docs/DigitalPulse.md
Normal file
15
targets/esp32/docs/DigitalPulse.md
Normal file
@ -0,0 +1,15 @@
|
||||
Digital Pulse
|
||||
===
|
||||
Espruino supports a command digitalPulse
|
||||
|
||||
##General##
|
||||
ESP32 supports a so called RMT with a lot of timers. This is defined generally to support Remote Control. Anyway we will use it to create digital pulses.
|
||||
|
||||
##Usage for Espruino##
|
||||
First version of digital pulse uses rmt driver.
|
||||
|
||||
There are 8 channel available. Each one with is connected to a pin. Timimg goes down to micro secs.
|
||||
|
||||
|
||||
##Status##
|
||||
Still waiting for my digital oscilloscope for testing.
|
||||
40
targets/esp32/docs/ESP32Specific.md
Normal file
40
targets/esp32/docs/ESP32Specific.md
Normal file
@ -0,0 +1,40 @@
|
||||
# ESP32 Specific
|
||||
A static class called "ESP32" is provided that supplies ESP32 specific APIs.
|
||||
Note that there is no "requires" needed for these functions. They are static
|
||||
and belong to the class. For example, to invoke the `reboot` method, one would
|
||||
code:
|
||||
|
||||
```
|
||||
ESP32.reboot();
|
||||
```
|
||||
|
||||
These include:
|
||||
|
||||
## ESP32.neopixelWrite
|
||||
Not yet implemented
|
||||
|
||||
## ESP32.getState
|
||||
Returns a Java Script object that has the following properties filled in:
|
||||
* `sdkVersion` - The version of the Espressif SDK that Espruino is using.
|
||||
* `freeHeap` - The amount of heap storage unused.
|
||||
|
||||
##ESP32.setLogLevel
|
||||
The ESP32 environment has built in diagnostics and logging. Calling this
|
||||
method changes the logging levels for either specific component or the
|
||||
environment as a whole. The signature of the function is:
|
||||
|
||||
`setLogLevel(tag, level)`
|
||||
|
||||
where:
|
||||
|
||||
* `tag` - The logging tag to specify. Use `*` for all tags.
|
||||
* `level` - The logging level to log at or better. The levels are:
|
||||
* verbose
|
||||
* debug
|
||||
* info
|
||||
* warn
|
||||
* error
|
||||
* none
|
||||
|
||||
##ESP32.reboot
|
||||
Reboot the ESP32 device.
|
||||
122
targets/esp32/docs/ESP32_and_Git.md
Normal file
122
targets/esp32/docs/ESP32_and_Git.md
Normal file
@ -0,0 +1,122 @@
|
||||
# How to GIT for Espruino(ESP32)
|
||||
Target of this is to be a help working with Git for ESP32 branch of Espruino.
|
||||
Lets assume, that you already worked with Git for your own project.
|
||||
If you are a total beginner, please go to Google and search for documents.
|
||||
To be honest, I did this some years ago, and don’t know for sure how this worked ;-)
|
||||
|
||||
Lets assume, we already have forked a repository from `https://github.com/espruino/Espruino` into our repository.
|
||||
Lets give it the name OurRepository and open a cmd for our git folder in documents. Usually I take Windows Power Shell
|
||||
for this.
|
||||
BTW, don’t forget to replace `OurRepository` by the name of your repository.
|
||||
There is no way, that I know, to sync a fork directly. Only way is to sync our local copy first and then sync forket
|
||||
repository from your local computer.
|
||||
First step is to clone sources to your local computer.
|
||||
|
||||
```
|
||||
git clone https://github.com/OurRepository/Espruino.git
|
||||
```
|
||||
|
||||
Thats easy, depending on your connection, this will take more or less time. During this process you will see
|
||||
something like this.
|
||||
|
||||
```
|
||||
Cloning into ‘Espruino’…
|
||||
remote: Counting objects: 33631, done.
|
||||
remote: Compressing objects: 100% (111/111), done.
|
||||
remote: Total 33631 (delta 41), reused 0 (delta 0), pack-reused 33517
|
||||
Receiving objects: 100% (33631/33631), 57.69 MiB | 5.21 MiB/s, done.
|
||||
Resolving deltas: 100% (22537/22537), done.
|
||||
Checking out files: 100% (2268/2268), done.
|
||||
```
|
||||
|
||||
Next we switch to the new directory, named `Espruino`.
|
||||
|
||||
```
|
||||
$ cd Espruino
|
||||
```
|
||||
|
||||
Now its time to switch to the branch for ESP32.
|
||||
|
||||
```
|
||||
git checkout ESP32
|
||||
```
|
||||
|
||||
Well its time for a more complex action. The original repository is usually some steps ahead to your fork.
|
||||
Means Gordon made some changes and these changes are not copied to your fork automatically.
|
||||
Before you can synchronize your fork from the original repository, an upstream needs to be created.
|
||||
This step has to be done only the first time.
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/espruino/Espruino.git
|
||||
```
|
||||
|
||||
Before using this, its a good idea to check actual status.
|
||||
|
||||
```
|
||||
git remote -v
|
||||
```
|
||||
|
||||
should see something like this
|
||||
|
||||
```
|
||||
origin https://github.com/OurRepository/Espruino.git (fetch)
|
||||
origin https://github.com/OurRepository/Espruino.git (push)
|
||||
upstream https://github.com/espruino/Espruino.git (fetch)
|
||||
upstream https://github.com/espruino/Espruino.git (push)
|
||||
```
|
||||
|
||||
Upstream is available, so lets use it. Let’s sync our local copy from the ESP32 branch in original repository
|
||||
for Espruino.
|
||||
|
||||
```
|
||||
git pull upstream ESP32
|
||||
```
|
||||
|
||||
Of course, there is a log from Git where you can see what happened. There will be some lines like this.
|
||||
|
||||
```
|
||||
remote: Counting objects: 71, done.
|
||||
remote: Compressing objects: 100% (71/71), done.
|
||||
remote: Total 71 (delta 31), reused 0 (delta 0), pack-reused 0
|
||||
Unpacking objects: 100% (71/71), done.
|
||||
From https://github.com/espruino/Espruino
|
||||
branch ESP32 -> FETCH_HEAD
|
||||
[new branch] ESP32 -> upstream/ESP32
|
||||
Updating 1f7a760..9e2b4db
|
||||
Fast-forward
|
||||
Makefile |6 +-
|
||||
boards/ESP32.py |2 +-
|
||||
...
|
||||
...
|
||||
targets/esp32/tests/simple_web_server.js |14 +
|
||||
targets/esp32/tests/timer1.js |3 +
|
||||
16 files changed, 1271 insertions(+), 46 deletions(-)
|
||||
create mode 100644 libs/network/esp32/network_esp32.c
|
||||
create mode 100644 libs/network/esp32/network_esp32.h
|
||||
...
|
||||
```
|
||||
|
||||
If you already have some changes for the source, its a good idea to do them now. Obviously, you can also save all the
|
||||
new things you got from Espruino(ESP32) directly to your fork.
|
||||
|
||||
```
|
||||
git push origin ESP32
|
||||
```
|
||||
|
||||
Once again you should get a log which looks like this
|
||||
|
||||
```
|
||||
Counting objects: 71, done.
|
||||
Delta compression using up to 4 threads.
|
||||
Compressing objects: 100% (71/71), done.
|
||||
Writing objects: 100% (71/71), 18.27 KiB | 0 bytes/s, done.
|
||||
Total 71 (delta 45), reused 0 (delta 0)
|
||||
remote: Resolving deltas: 100% (45/45), completed with 14 local objects.
|
||||
To https://github.com/OurRepository/Espruino.git
|
||||
1f7a760..9e2b4db ESP32 -> ESP32
|
||||
```
|
||||
|
||||
Well we are done with, our fork is in sync with original Espruino. At least for the ESP32 branch ;-) Git is a very complex
|
||||
tool and sometimes it looks too complex. Like others I would prefer a nice UI where only a button needs to be pushed and
|
||||
everything runs like magic. If there is a tool like this, please send me a link ;-)<br>If you want to get some more helpful
|
||||
info around Git or other it fields, give the guys at SitePoint a try. They have been a big help in creating this tutorial.</p>
|
||||
74
targets/esp32/docs/GPIOHandling.md
Normal file
74
targets/esp32/docs/GPIOHandling.md
Normal file
@ -0,0 +1,74 @@
|
||||
GPIO
|
||||
====
|
||||
ESP32 has a lot of GPIOs and supports different protocols etc. In this document we focus on simple GPIO binary handling. Documents for SPI, Analog, PWM etc. will follow.
|
||||
|
||||
###Available GPIOs / pins###
|
||||
Even having GPIO named from 0 to 39, does not mean, we have all available. Some of them don't even exist, and only a few are available on DevkitC.
|
||||
|
||||
| CPU pin | GPIO | Devkit C|
|
||||
| --- | --- | --- |
|
||||
| 5 | 36 | X |
|
||||
| 6 | 37 | |
|
||||
| 7 | 38 | |
|
||||
| 8 | 39 | X |
|
||||
| 10 | 34 | X |
|
||||
| 11 | 35 | X |
|
||||
| 12 | 32 | X |
|
||||
| 13 | 33 | X |
|
||||
| 14 | 25 | X |
|
||||
| 15 | 26 | X |
|
||||
| 16 | 27 | X |
|
||||
| 17 | 14 | X |
|
||||
| 18 | 12 | X |
|
||||
| 20 | 13 | X |
|
||||
| 21 | 15 | X |
|
||||
| 22 | 2 | X|
|
||||
| 23 | 0 | X|
|
||||
| 24 | 4 | X|
|
||||
| 25 | 16 | X |
|
||||
| 27 | 17 | X |
|
||||
| 28 | 9 | |
|
||||
| 29 | 10 | |
|
||||
| 30 | 11 | |
|
||||
| 31 | 6 | |
|
||||
| 32 | 7 | |
|
||||
| 33 | 8 | |
|
||||
| 34 | 5 | X |
|
||||
| 35 | 18 | X |
|
||||
| 36 | 23 | X |
|
||||
| 38 | 19 | X |
|
||||
| 39 | 22 | X |
|
||||
| 40 | 32 | |
|
||||
| 41 | 10 | |
|
||||
| 42 | 21 | X |
|
||||
|
||||
###Binary I/O###
|
||||
Espruino/targets/esp32/jshardware.c is the main connection between Espruino Core and special sources to handle ESP32 specific commands.
|
||||
For simple GPIO handling we have to fill following functions. For more information/detailed please go to source
|
||||
|
||||
| Function | Description |
|
||||
| --- | --- |
|
||||
| jshPinSetState | Set the state of the specific pin. |
|
||||
| jshPinGetState | return current State of pin |
|
||||
| jshPinSetValue | set the value of pin |
|
||||
| jshPinGetValue | get the value of pin |
|
||||
|
||||
###Interrupts###
|
||||
For commands like setWatch fast response of changes on pin is a must. Fastest way is catching interrupts. Following functions will do this particular job
|
||||
|
||||
| Function | Description |
|
||||
| --- | --- |
|
||||
| in jshInit | add a line to register GPIO interrupts (gpio_isr_register) |
|
||||
| gpio_intr_test | function to handle interrupts, calls jshPushIOWatchEvent for each changed pin that is enabled for interrupt |
|
||||
| jshGetWatchedPinState | Get the state of the pin associated with the event flag. Take care on parameter its IOEventFlags not pin |
|
||||
| jshPinWatch | Enables or disables interrupt for pin |
|
||||
| jshIsEventForPin | Determine if a given event is associated with a given pin |
|
||||
|
||||
###General functions###
|
||||
Please have in mind, there are pins and IOEventFlags. Handling them is simple, we only have to add EV_EXTIO. There are some definitions in Espruino Core. In jshardware.c we handle it this way. May be in future we find a better way.
|
||||
|
||||
| Function | Description |
|
||||
| --- | --- |
|
||||
| pinToEV_EXTI | maps a pin to an event |
|
||||
| | maping an event to a pin is done by subtracting EV_EXTI0 from IOEventFlag |
|
||||
| pinToESP32Pin | converts a number to a gpio_num_t |
|
||||
26
targets/esp32/docs/HardwareTimer.md
Normal file
26
targets/esp32/docs/HardwareTimer.md
Normal file
@ -0,0 +1,26 @@
|
||||
Hardware Timer
|
||||
===
|
||||
Espruino uses Highspeed hardware timer for functions like waveform.
|
||||
|
||||
##General##
|
||||
ESP32 supports 2 groups of timer, both having 2 timer.
|
||||
esp-idf supports driver for timer with components/driver/include/driver/timer.h
|
||||
|
||||
##Conection to Espruino##
|
||||
An interrupt needs to be defined with IRAM_ATTR. To connect to Espruino, the isr (interrupt service routine) calls jstUtilTimerInterruptHandler.
|
||||
|
||||
##Problem##
|
||||
This function is not defined as IRAM_ATTR or something similiar. Due to this, or whatever other reason we get a reset after some calls. There could be many reasons for that like:
|
||||
- problems with floating point
|
||||
- running out of memory, since isr use their own stack
|
||||
- running out of time for isr
|
||||
- something else ???
|
||||
|
||||
##Solution##
|
||||
As long as we don't know better, the solution is to seperate isr from calling jstUtilTimerInterruptHandler.
|
||||
For that we create a new task, which waits for a notification and after receiving one, calls the function in Espruino. Inside the isr we now have to send the notification. Sending a notification is done with vTaskNotifyGiveFromISR, a function of FREErtos.
|
||||
Waiting for the notification uses ulTaskNotifyTake, another function in FREErtos.
|
||||
|
||||
##Status##
|
||||
A first step with a simple waveform on an DAC port (GPIO25/GPIO26) runs without any crashes now. Thats good part of the answer, badly it does not change output :-(
|
||||
We are working on that......
|
||||
30
targets/esp32/docs/Install.md
Normal file
30
targets/esp32/docs/Install.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Installation of Espruino
|
||||
A build of Espruino consists of three binary files called:
|
||||
|
||||
* espruino_esp32.bin
|
||||
* bootloader.bin
|
||||
* paritions_singleapp.bin
|
||||
|
||||
These files are loaded into an ESP32 using the `esptool.py` command. An example
|
||||
of usage would be:
|
||||
|
||||
```
|
||||
esptool.py \
|
||||
--chip esp32 \
|
||||
--port "/dev/ttyUSB0" \
|
||||
--baud 115200 \
|
||||
write_flash \
|
||||
-z \
|
||||
--flash_mode "dio" \
|
||||
--flash_freq "40m" \
|
||||
0x10000 espruino_esp32.bin \
|
||||
0x1000 /home/kolban/esp32/Espruino/template/build/bootloader/bootloader.bin \
|
||||
0x8000 /home/kolban/esp32/Espruino/template/build/partitions_singleapp.bin
|
||||
|
||||
```
|
||||
|
||||
Remember to put your ESP32 into flash mode before running the command and then
|
||||
reboot after loading the program.
|
||||
|
||||
The JavaScript development tooling (WebIDE) is best run through Chrome by installing
|
||||
the [Espruino Web IDE](https://chrome.google.com/webstore/detail/espruino-web-ide/bleoifhkdalbjfbobjackfdifdneehpo).
|
||||
26
targets/esp32/docs/Menuconfig.md
Normal file
26
targets/esp32/docs/Menuconfig.md
Normal file
@ -0,0 +1,26 @@
|
||||
# make menuconfig
|
||||
Within the template project that builds the ESP-IDF environment, there is a
|
||||
configuration file called `sdkconfig`. While this file can be edited by hand
|
||||
there is an elegant full screen text based user interface for editing. We can
|
||||
bring this up by running `make menuconfig`. This provides a menu driven editor
|
||||
where properties can be changed.
|
||||
|
||||
Some options *must* be changed for correct operation of Espruino. These
|
||||
are:
|
||||
|
||||
* Component config -> LWIP -> Enable SO_REUSEADDR option [Enable]
|
||||
* Component config -> ESP32-specific config -> Task watchdog [Disable]
|
||||
* Component config > FreeRTOS -> Halt when an SMP-untested function is called [Disable]
|
||||
|
||||
Other options can be changed at your discretion for changes in the environment that
|
||||
are primarily to taste. Examples that I would consider are:
|
||||
|
||||
* Bootloader config -> Bootloader log verbosity - Consider changing this to `Verbose`.
|
||||
* Serial flasher config -> Default baud rate - I have had success with 921600.
|
||||
* Serial flasher config -> Use compressed upload - I have had success with this enabled.
|
||||
* Component config -> Log output -> Default log verbosity - Consider changing this to `Verbose`.
|
||||
* Component config -> Log output -> Use ANSI terminal colors in log output - I switch this off from the default of on.
|
||||
|
||||
When re-importing the latest versions of ESP-IDF, we will likely overwrite any changes
|
||||
we made here. Either we copy the `sdkconfig` you have been using and put it back after
|
||||
a refresh or else re-run `make menuconfig` after a refresh.
|
||||
27
targets/esp32/docs/PWM.md
Normal file
27
targets/esp32/docs/PWM.md
Normal file
@ -0,0 +1,27 @@
|
||||
PWM
|
||||
===
|
||||
Espruino supports Analog output using PWM
|
||||
|
||||
##General##
|
||||
ESP32 supports (at least) 2 optiins for PWM. Both have pros and cons.
|
||||
- sigmadelta
|
||||
driver for sigmadelta is very easy to use. Problem is a limitation in frequency.
|
||||
Base of frequency is 80Mhz, which can be divided by a values from 1 to 255.
|
||||
Therefore a frequency of 30khz is impossible this way
|
||||
- ledc
|
||||
driver for ledc is designed to control leds. Not a big surprise, if you see the name :-)
|
||||
Driver allows a lot of options, like fadein and fadeout. There are 8 channel, which can be assigned to a GPIO. In the background are 4 timer, where each channel needs to be assigned to a specific timer. Therefore only 4 different frequencies are possible.
|
||||
Last not least, Frequency is limited to about 75Khz
|
||||
|
||||
##Usage for Espruino##
|
||||
First version of PWM uses ledc driver. Usually, this matches needs for frequency much more than sigmadelta. Mapping of PWM channel to timer is done in a special way.
|
||||
There are 5 channel usable, as long as 5Khz are ok for frequency. Channels are internally controlled. If you try to use more than 5, you will get a message.
|
||||
Left 3 channels are designed to support a frequency of your choice, as long as it is between 1hz and 78 Khz. If you try to use a 4th channel with a frequency, other than 5Khz you will a meesage.
|
||||
|
||||
##Problem##
|
||||
Handling of PWM with those 5/3 method is not always easy to follow. As long as we don't have a better solution, its better to have this than nothing.
|
||||
Limitation of frequency is boring, but as long as we use it for analog output, it should be acceptable.
|
||||
Please have in mind, PWM via analog always need a lowpass filter, usually a simple RC.
|
||||
|
||||
##Status##
|
||||
As mentioned above, this is a first step. Hopefully we get a better solution in the future. We could build our own solution, using RMT. If somebody wants to go into this direction, you are welcome. In that case please take care on implementation of digitalPulse, see jshardwarPulse for more information.
|
||||
276
targets/esp32/docs/README.md
Normal file
276
targets/esp32/docs/README.md
Normal file
@ -0,0 +1,276 @@
|
||||
#Notes on the development of Espruino for ESP32
|
||||
|
||||
The github URL for core Espruino is:
|
||||
|
||||
https://github.com/espruino/Espruino.git
|
||||
|
||||
New board will trigger on
|
||||
ESP32=1
|
||||
|
||||
To build, we need to set
|
||||
```
|
||||
export ESP32=1
|
||||
export ESP_IDF_PATH=/path to ESP_IDF
|
||||
export PATH=/opt/xtensa-esp32-elf/bin:$PATH
|
||||
```
|
||||
|
||||
##The Espruino Github
|
||||
Espruino is maintained as Open Source on Github. The master project repository is the organization called "espruino" that can be found here: `https://github.com/espruino`
|
||||
|
||||
The leader/founder/brains/owner behind the whole shooting match is Gordon Williams.
|
||||
Within the espruino Github organization, we will find a Github repository called "Espruino".
|
||||
|
||||
`https://github.com/espruino/Espruino`
|
||||
|
||||
This is the master repository for the project.
|
||||
Within this repository there is a branch called "ESP32". It is against this branch we will be performing our work.
|
||||
Note: The thinking is that we will perform all changes necessary within that branch so that there will be no breakage of the master work should something go wrong. The ultimate goal is that at some date in the future, the majority of the work against an Espruino port to ESP32 will be considered "ready" and the work performed in the "ESP32" branch will be merged into the "master" branch and then on-going maintenance performed there.
|
||||
|
||||
Let us assume (as is actually the case at the time of writing) that the ESP32 branch does not yet exist. The first step will be someone with suitable authorization create that branch. Note that an Espruino on ESP32 developer will not be performing these steps. They are recorded here for interest and for potential future projects.
|
||||
The recipe to perform the branch creation task is as follows:
|
||||
|
||||
* Clone a local copy of Espruino
|
||||
```
|
||||
$ git clone https://github.com/espruino/Espruino.git
|
||||
```
|
||||
|
||||
* Change into the directory for the clone
|
||||
```
|
||||
$ cd Espruino
|
||||
```
|
||||
|
||||
* Create a new branch
|
||||
```
|
||||
$ git branch ESP32
|
||||
```
|
||||
|
||||
* Checkout the branch
|
||||
```
|
||||
$ git checkout ESP32
|
||||
```
|
||||
|
||||
* Push the changes back to master in Github
|
||||
```
|
||||
$ git push -u origin --all
|
||||
```
|
||||
|
||||
And now we will have created a branch.
|
||||
|
||||
## Coding standards
|
||||
|
||||
<Do we have these already written?>
|
||||
No tabs, indent by two spaces
|
||||
|
||||
## Build instructions
|
||||
In order to build Espruino for an ESP32, I am assuming you have a Linux environment at your disposal. While there is no technical reason you can't build Espruino on a different operating system, these notes assume Linux. If you don't have a Linux platform, consider using a Raspberry Pi or VirtualBox.
|
||||
We will need three major environmental components in order to build Espruino. These are:
|
||||
|
||||
* An Xtensa ESP32 tool chain
|
||||
* A copy of the Espressif IoT Development Framework (ESP-IDF)
|
||||
* A copy of an ESP-IDF template application
|
||||
|
||||
### Let us now break these down.
|
||||
The first is the Xtensa tool chain. The processor on an ESP32 is made by Xtensa and has its own architecture and instruction set. When we compile Espruino, we will be generating binary files that are the compiled C files. These binary files contain the executable instructions and data that will eventually be loaded on the ESP32. A compiler takes our source code and builds the resulting compiled code. Our source is C language in text files and our result must be Xtensa binaries. A tool chain is a suite of tools that take us from the source to the compiled binaries. These include C compilers, linkers, archivers and a few others. Espressif makes available a down loadable version of the Xtensa tool chain for Linux on x86 or x86-64. If you have previously been working with the ESP8266 toolchains, make sure that you realize that the toolchain for ESP32 is distinct from that of the ESP8266. The source code for the compilers is also available and can be downloaded and compiled yourself. I had to do this to get the tool chain running on the ARM architecture for my Raspberry Pi. I don't recommend building your own compiler unless you have a good reason. Instead find a binary version and download and trust that it won't do mischief on your machine.
|
||||
In my recipes I choose to install the tool chain in /opt/xtensa-esp32-elf and add /opt/xtensa-esp32-elf/bin to your environmental PATH.
|
||||
|
||||
Next we need the ESP-IDF. This is the core of the framework that is the foundation upon which we build Espruino.
|
||||
This package provides the libraries we link against in order to leverage the services of the ESP32 environment.
|
||||
The package contains modules for WiFi, TCP/IP sockets, GPIO and much more. The package is distributed from Github and contains
|
||||
pre-built libraries distributed in binary format as well as many modules that are distributed in source and need to be compiled.
|
||||
|
||||
Next we need an instance of an ESP-IDF template application. This is another project type that is extractable from Github.
|
||||
The true purpose of this project type is to be the basis for one of your own ESP32 applications. The intent is that you download this
|
||||
template application, rename it to reflect the name you want for your target app and then start editing the source for your own
|
||||
purposes. It also contains a Makefile which knows how to build a full binary ready for flashing onto the ESP32.
|
||||
At this point you may be thinking to yourself that this seems a strange component to include
|
||||
in our Espruino story … but here is the thinking. The ESP-IDF is provided partially in binary format and partially
|
||||
as source files that need compiled. Because of this, we would need to compile the ESP-IDF to be able to have all
|
||||
the linkable libraries. Unfortunately, as of this time, there doesn't appear to be a recipe to simply "build all the
|
||||
ESP-IDF libraries". Instead, it is the template application which builds them for us. When we download a
|
||||
ready-to-compile template and ask it to build, the result is not only a compiled application … but a side
|
||||
effect is that all the ESP-IDF libraries we need are also compiled and placed in directories for us to link
|
||||
against. While it might be feasible to incorporate these rules to build all the ESP-IDF libraries that
|
||||
Espruino requires into the Espruino Makefile, at this time we have decided that there is no immediate need to do that.
|
||||
If we download the ESP-IDF and download the ESP-IDF template application and run a compile against that application,
|
||||
the result (from Espruino build perspective) is that we have all the libraries we need to link against with minimal work
|
||||
on our part. Thankfully, the recipe to achieve these tasks is very easy and very repeatable.
|
||||
|
||||
In early version of Espruino port, SDK for esp32 did not support I2C and SPI.
|
||||
Only option at that time was to use Arduino related driver.
|
||||
This changed with new SDK which supports I2C, I2S, SPI and a lot of other driver.
|
||||
Therefore we don't need Arduino driver anymore. If somebody still wants to use them, we will keep a description at the end of this document.
|
||||
|
||||
Here are the instructions that need only be followed once.
|
||||
* In your home directory (or wherever you want the root of your build to be) create a directory called "esp32".
|
||||
```
|
||||
$ mkdir esp32
|
||||
```
|
||||
|
||||
* Change into that directory. This directory is what we will refer to as the ESP32 root directory in our story.
|
||||
```
|
||||
$ cd esp32
|
||||
```
|
||||
|
||||
* Extract the ESP-IDF from Github
|
||||
```
|
||||
$ git clone --recursive https://github.com/espressif/esp-idf.git
|
||||
```
|
||||
|
||||
* Change into the newly created esp-idf folder.
|
||||
```
|
||||
$ cd esp-idf
|
||||
```
|
||||
|
||||
* Update the submodule.
|
||||
```
|
||||
$ git submodule update --init
|
||||
```
|
||||
|
||||
* Change back up to the ESP32 root directory.
|
||||
```
|
||||
$ cd ..
|
||||
```
|
||||
|
||||
* Extract the ESP-IDF template application to a folder called "template".
|
||||
```
|
||||
$ git clone https://github.com/espressif/esp-idf-template.git template
|
||||
```
|
||||
|
||||
* Edit a file called setenv.sh and add the following lines:
|
||||
```
|
||||
#!/bin/bash
|
||||
export ESP_IDF_PATH=$(pwd)/esp-idf
|
||||
export IDF_PATH=$(pwd)/esp-idf
|
||||
export ESP_APP_TEMPLATE_PATH=$(pwd)/template
|
||||
export ESP32=1
|
||||
[[ ":$PATH:" != *":/opt/xtensa-esp32-elf/bin:"* ]] && PATH="/opt/xtensa-esp32-elf/bin:${PATH}"
|
||||
```
|
||||
|
||||
* Make the script executable:
|
||||
```
|
||||
$ chmod u+x setenv.sh
|
||||
```
|
||||
|
||||
* Execute the environment script to set the variables. You will need to re-run this each time you open a new shell for building Espruino.
|
||||
```
|
||||
$ . ./setenv.sh
|
||||
```
|
||||
|
||||
* Change into the new template directory.
|
||||
```
|
||||
$ cd template
|
||||
```
|
||||
|
||||
* If you need Arduino, you have to do it here with commands at the end of this document
|
||||
|
||||
* Run the `make menuconfig`.
|
||||
```
|
||||
$ make menuconfig
|
||||
```
|
||||
|
||||
* Change some of the settings necessary for Espruino:
|
||||
```
|
||||
Component config -> LWIP -> Enable SO_REUSEADDR option [Enable]
|
||||
Component config -> ESP32-specific config -> Task watchdog [Disable]
|
||||
sooner or later we need to find a way to refresh Task watchdog
|
||||
Component config -> FreeRTOS -> Halt when an SMP-untested function is called [Disable]
|
||||
some functions are marked as "SMP-untested" and a call results in a reset
|
||||
on our test they work fine, and for testing we need some of them
|
||||
```
|
||||
|
||||
* Perform a build to create the libraries and the template application.
|
||||
```
|
||||
$ make
|
||||
```
|
||||
|
||||
* Change back up to the ESP32 root directory.
|
||||
```
|
||||
$ cd ..
|
||||
```
|
||||
|
||||
* Extract Espruino source from YOUR fork of Espruino:
|
||||
```
|
||||
$ git clone https://github.com/YOURGITHUBID/Espruino.git
|
||||
```
|
||||
|
||||
* Change into the Espruino folder.
|
||||
```
|
||||
$ cd Espruino
|
||||
```
|
||||
|
||||
$ Build Espruino:
|
||||
```
|
||||
$ make
|
||||
```
|
||||
|
||||
If all has built correctly, you will now find that you have a flash-able binary representing Espruino for the ESP32.
|
||||
|
||||
In summary, here are the steps again without commentary:
|
||||
|
||||
```
|
||||
$ mkdir esp32
|
||||
$ cd esp32
|
||||
$ git clone --recursive https://github.com/espressif/esp-idf.git
|
||||
$ cd esp-idf
|
||||
$ git submodule update --init
|
||||
$ cd ..
|
||||
$ git clone https://github.com/espressif/esp-idf-template.git template
|
||||
$ nano setenv.sh
|
||||
>>>
|
||||
#!/bin/bash
|
||||
export ESP_IDF_PATH=$(pwd)/esp-idf
|
||||
export IDF_PATH=$(pwd)/esp-idf
|
||||
export ESP_APP_TEMPLATE_PATH=$(pwd)/template
|
||||
export ESP32=1
|
||||
[[ ":$PATH:" != *":/opt/xtensa-esp32-elf/bin:"* ]] && PATH="/opt/xtensa-esp32-elf/bin:${PATH}"
|
||||
<<<
|
||||
$ chmod u+x setenv.sh
|
||||
$ . ./setenv.sh
|
||||
$ cd template
|
||||
$ make menuconfig
|
||||
$ make
|
||||
$ cd ..
|
||||
$ git clone https://github.com/YOURGITHUBID/Espruino.git
|
||||
$ cd Espruino
|
||||
$ make
|
||||
```
|
||||
|
||||
### Include Arduino driver###
|
||||
* Make the components folder.
|
||||
```
|
||||
$ mkdir components
|
||||
```
|
||||
|
||||
* Change into the components folder.
|
||||
|
||||
```
|
||||
$ cd components
|
||||
```
|
||||
|
||||
* Retrieve the Arduino-esp32 project
|
||||
|
||||
```
|
||||
$ git clone https://github.com/espressif/arduino-esp32.git
|
||||
```
|
||||
|
||||
* Edit the `main.cpp` source file
|
||||
```
|
||||
$ nano arduino-esp32/cores/esp32/main.cpp
|
||||
>>> Comment out app_main
|
||||
/*
|
||||
extern "C" void app_main()
|
||||
{
|
||||
init();
|
||||
initVariant();
|
||||
initWiFi();
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 4096, NULL, 1, NULL, 1);
|
||||
}
|
||||
*/
|
||||
<<<
|
||||
```
|
||||
|
||||
* Change back up to the template folder
|
||||
```
|
||||
$ cd ..
|
||||
```
|
||||
|
||||
28
targets/esp32/docs/RTOS_for_Espruino.md
Normal file
28
targets/esp32/docs/RTOS_for_Espruino.md
Normal file
@ -0,0 +1,28 @@
|
||||
RTOS for Espruino
|
||||
===
|
||||
With RTOS we get a new world for Espruino. Before I forget to mention, actual sources are on very early state. Usually Espruino is very well tested, for this new functions, hmm, let me say, hmm, its more like a proof of concept.
|
||||
To get RTOS running for Espruino on ESP32 you have to define RTOS=1 before starting make.
|
||||
###General
|
||||
RTOS is a shortcut for RealTime Operating System. Realtime OS are welknown in the world, usually they support running more than one task. In big systems, number of tasks can be very high. Obviously, this needs a lot of memory and some control of tasks. Words like priorities, queues, semaphores and more belong to this world.
|
||||
Lets take a first look into this world to see, what Espruino can do with that.
|
||||
###Tasks
|
||||
From outside tasks are seperate applications running on a computer at the same time. They could work together, or totally independent from all others.
|
||||
Ususally in the world of micro computers, we have one CPU only. Ok, ESP32 has two of them, but even with 2 CPUs, there must be a way to have several application running at the same time.
|
||||
Its a good point to switch wording now from application to task. A task can be a full sized application like Espruino. But it can also be a simple function like reading input from serial and prepare it for other tasks. Even something like a blinker can be a task.
|
||||
One of the magic words for tasks is priority. Based on priority, the OS decides how often a task gets time to work. This will not really work with an endless loop.
|
||||
Next magic words are interrupts. Interrupts like a timer will suspend running task, make a decision based on priority which task should get some time and resumes that task.
|
||||
###Queues
|
||||
Lets take a closer look to the concept of the uart reading task mentioned earlier. This task reads data and prepares the data for later use. Tasks like this are often used, but working for themselve sounds senseless. Reading keystrokes from a console for example without doing anything is like talking to a wall.
|
||||
Good for us, we have a solution and this is called Espruino. Espruino uses uart info to run complex javascript functions. But how could the console task tell Espruino about incomin keystrokes.
|
||||
The way RTOS supports this is called a queue. One task, in our case the console task writes data into this queue and another task reads data from this queue.
|
||||
###Task interaction###
|
||||
RTOSfree supports a lot of functions to interact between tasks. Queues have already been mentioned in previous chapter. Other options are semaphores and notification.
|
||||
Notification are an option to awake a task really quick. Each task has an area of memory which is available for function calls from other tasks. Simple action is, that one task is waiting for "something", and another task is telling that "something" happened.
|
||||
###API calls
|
||||
RTOS supports a lot of functions to work with queues and tasks on a low level. Good part of low level is, you can do a lot of special things. Bad part is, you have to do everything on this low level.
|
||||
Usually you combine low level calls to easy to use utilities. As a first step we have some functions in targets/esp32/rtosutil.c. Take a short look to the header file to get more information around the functions supported.
|
||||
###Espruino commands
|
||||
Rtosutil supports functions on level of C. To use them in Espruino, they need a wrapper. And this wrapper is named jswrap_rtos.c. For each command you can see the wrapper data in the source. BTW, Espruino uses these lines to create its own documentation.
|
||||
###Examples in Javascript
|
||||
have to be done
|
||||
|
||||
18
targets/esp32/docs/SPI.md
Normal file
18
targets/esp32/docs/SPI.md
Normal file
@ -0,0 +1,18 @@
|
||||
# SPI
|
||||
The ESP32 has three SPI buses called HSPI, VSPI and FSPI. Of these three, HSPI
|
||||
and VSPI are available for our use. The default pin mappings for these
|
||||
buses are:
|
||||
|
||||
| SPI | MOSI | MISO | CLK | SS |
|
||||
+------+------+------+-----+----+
|
||||
| HSPI | 13 | 12 | 14 | 15 |
|
||||
| VSPI | 23 | 19 | 18 | 5 |
|
||||
|
||||
In the world of Espruino, there are logical SPIs called SPI1 and SPI2.
|
||||
We have mapped SPI1 -> HSPI and SPI2 -> VSPI.
|
||||
|
||||
As of 2016-10-26 the ESP-IDF SPI drivers have NOT yet been released however
|
||||
we have a technique that is available to us through the use of the Arduino-ESP32
|
||||
project. We have linked the Arduino-ESP32 code with our current Espruino to achieve
|
||||
SPI. This will keep us going until the proper libraries are released. The Espruino
|
||||
externals will not be affected by our internal SPI implementation.
|
||||
55
targets/esp32/docs/SaveAndLoad.md
Normal file
55
targets/esp32/docs/SaveAndLoad.md
Normal file
@ -0,0 +1,55 @@
|
||||
# Save and Load programs
|
||||
When we have entered a program, we need to be able to save that program so that when the
|
||||
device is restarted, the program loads and runs.
|
||||
|
||||
The primary mechanism for this is the routine called `jsfSaveToFlash` found in `jswrap_flash.c`.
|
||||
|
||||
The signature for this is:
|
||||
|
||||
```
|
||||
void jsfSaveToFlash(JsvSaveFlashFlags flags, JsVar *bootCode)
|
||||
```
|
||||
|
||||
It assumes that the program will be saved starting at `FLASH_SAVED_CODE_START`. The first
|
||||
word (4bytes) is the amount of boot code saved. The second word is the end address of
|
||||
decompressed JS code. The boot code is saved at FLASH_SAVED_CODE_START+8. The saved
|
||||
state starts at FLASH_SAVED_CODE_START + 8 + boot_code_length.
|
||||
|
||||
In the following table, the offsets are relative to FLASH_SAVED_CODE_START
|
||||
|
||||
| Name | Address offset
|
||||
+------------------------+-----------------------
|
||||
| boot_code_length | 0
|
||||
| <end> | 4
|
||||
| Boot code | 8
|
||||
| Saved state | 8 + boot_code_length
|
||||
|
||||
`FLASH_MAGIC` is `0xDEADBEEF`.
|
||||
`FLASH_MAGIC_LOCATION` is `FLASH_SAVED_CODE_START + FLASH_CODE_LENGTH - 4`.
|
||||
`FLASH_CODE_LENGTH` is `65536`.
|
||||
|
||||
The `ESP32.py` file describes the flasg details in a section called `saved_code`:
|
||||
|
||||
```
|
||||
'saved_code' : {
|
||||
'address' : 0x100000,
|
||||
'page_size' : 4096,
|
||||
'pages' : 16,
|
||||
'flash_available' : 960, # firmware can be up to this size
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
jsfSaveToFlash_writecb(unsigned char ch, uint32_t *cbdata)
|
||||
```
|
||||
Write 1 byte specified by `ch` to flash.
|
||||
|
||||
```
|
||||
jsfSaveToFlash_checkcb(unsigned char ch, uint32_t *cbdata)
|
||||
```
|
||||
Validate that the character supplied can be read back.
|
||||
|
||||
```
|
||||
bool jsfFlashContainsCode()
|
||||
```
|
||||
Validate that the data contains code.
|
||||
38
targets/esp32/docs/TasksInterruptsEtc.md
Normal file
38
targets/esp32/docs/TasksInterruptsEtc.md
Normal file
@ -0,0 +1,38 @@
|
||||
Internals
|
||||
===
|
||||
RTOS and the SDK for ESP32 bring up some new screws and bolts.
|
||||
In this document, we will list at least some of them.
|
||||
|
||||
##Tasks##
|
||||
Rtos supports a simple form of tasks. These tasks get a priority on start and some other information.
|
||||
|
||||
| Task | Stack | Priority | CPU |
|
||||
| --- | --- | --- | --- |
|
||||
| EspruinoTask | 10000 | 5 | 0 |
|
||||
| ConsoleTask | 2048 | 20 | 0 |
|
||||
| TimerTask | 2048 | 19 | 0 |
|
||||
|
||||
|
||||
##Interrupt Level##
|
||||
Each realtime OS uses interrupts, and so does RTOS. There are some predefined or reserved for future use. For more info see esp-idf/components/esp32/include/soc/soc.h line 259ff..
|
||||
|
||||
Based on actual version of esp-idf, interrupt levels are assigned automatically.
|
||||
|
||||
##Timer##
|
||||
ESP32 generally support 2 groups of timers each having 2 timer. Timer is used for interrupt driven handling inside Espruino like Waveforms.
|
||||
|
||||
| Group | Timer | used for |
|
||||
| --- | --- | --- |
|
||||
| 0 | 0 | Espruino Util Timer |
|
||||
| 0 | 1 | testing only |
|
||||
| 1 | 0 | free |
|
||||
| 1 | 1 | free |
|
||||
|
||||
##Uarts##
|
||||
ESP32 supports 3 uarts, which can be assigned to GPIO ports. Espruino right now only uses uart_num_0 for console.
|
||||
|
||||
| Uart | used for |
|
||||
| --- | --- |
|
||||
| uart_num_0 | espruino console |
|
||||
| uart_num_1 | free |
|
||||
| uart_num_2 | free |
|
||||
40
targets/esp32/docs/WIFI.md
Normal file
40
targets/esp32/docs/WIFI.md
Normal file
@ -0,0 +1,40 @@
|
||||
# ESP32 and WiFi
|
||||
Using the ESP8266 board as a model, we must implement the ESP32 WiFi functions. This will entail
|
||||
the creation of a new source file called `jswrap_esp32_network.c` which will live in
|
||||
`libs/network/esp32`. There will also be a corresponding `jswrap_esp32_network.h`.
|
||||
|
||||
The majority of the WiFi API is documented in the Espruino docs here:
|
||||
|
||||
http://www.espruino.com/Reference#Wifi
|
||||
|
||||
This will expose a module called `Wifi` which will have the following static methods defined
|
||||
upon it:
|
||||
|
||||
* `connect` - Connect to an access point
|
||||
* `disconnect`
|
||||
* `getAPDetails`
|
||||
* `getAPIP`
|
||||
* `getDetails`
|
||||
* `getHostByName`
|
||||
* `getHostname`
|
||||
* `getIP`
|
||||
* `getStatus`
|
||||
* `ping`
|
||||
* `restore`
|
||||
* `save`
|
||||
* `scan`
|
||||
* `setConfig`
|
||||
* `setHostname`
|
||||
* `startAP`
|
||||
* `stopAP`
|
||||
|
||||
# Implementation status
|
||||
|
||||
## connect
|
||||
Working.
|
||||
|
||||
## disconnect
|
||||
Working.
|
||||
|
||||
## All others
|
||||
Not yet implemented
|
||||
154
targets/esp32/i2c.c
Normal file
154
targets/esp32/i2c.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* This file is designed to support i2c functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Rhys Williams (wilberforce)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "i2c.h"
|
||||
#include "driver/i2c.h"
|
||||
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
|
||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||
|
||||
/* To do:
|
||||
support both i2c ports - done
|
||||
Test!
|
||||
Stop bits param - bool sendStop
|
||||
https://esp-idf.readthedocs.io/en/latest/api/i2c.html
|
||||
|
||||
*/
|
||||
|
||||
static esp_err_t checkError( char * caller, esp_err_t ret ) {
|
||||
switch(ret) {
|
||||
case ESP_OK: break;
|
||||
case ESP_ERR_INVALID_ARG: {
|
||||
jsError( "%s:, Parameter error\n", caller );
|
||||
break;
|
||||
}
|
||||
case ESP_FAIL: {
|
||||
jsError( "%s:, slave doesn't ACK the transfer.\n", caller );
|
||||
break;
|
||||
}
|
||||
case ESP_ERR_TIMEOUT: {
|
||||
jsError( "%s:, Operation timeout because the bus is busy.\n", caller );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
jsError( "%s:, unknown error code %d, \n", caller, ret );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getI2cFromDevice( IOEventFlags device ) {
|
||||
switch(device) {
|
||||
case EV_I2C1: return I2C_NUM_0;
|
||||
case EV_I2C2: return I2C_NUM_1;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set-up I2C master for ESP32, default pins are SCL:21, SDA:22. Only device I2C1 is supported
|
||||
* and only master mode. */
|
||||
void jshI2CSetup(IOEventFlags device, JshI2CInfo *info) {
|
||||
int i2c_master_port = getI2cFromDevice(device);
|
||||
if (i2c_master_port == -1) {
|
||||
jsError("Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
}
|
||||
Pin scl;
|
||||
Pin sda;
|
||||
if ( i2c_master_port == I2C_NUM_0 ) {
|
||||
scl = info->pinSCL != PIN_UNDEFINED ? info->pinSCL : 21;
|
||||
sda = info->pinSDA != PIN_UNDEFINED ? info->pinSDA : 22;
|
||||
}
|
||||
// Unsure on what to default these pins to?
|
||||
if ( i2c_master_port == I2C_NUM_1 ) {
|
||||
scl = info->pinSCL != PIN_UNDEFINED ? info->pinSCL : 16;
|
||||
sda = info->pinSDA != PIN_UNDEFINED ? info->pinSDA : 17;
|
||||
}
|
||||
|
||||
i2c_config_t conf;
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = pinToESP32Pin(sda);
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.scl_io_num = pinToESP32Pin(scl);
|
||||
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.master.clk_speed = info->bitrate;
|
||||
esp_err_t err=i2c_param_config(i2c_master_port, &conf);
|
||||
if ( err == ESP_ERR_INVALID_ARG ) {
|
||||
jsError("jshI2CSetup: Invalid arguments");
|
||||
return;
|
||||
}
|
||||
err=i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
|
||||
if ( err == ESP_OK ) {
|
||||
jsWarn("jshI2CSetup: driver installed, sda: %d sdl: %d freq: %d, \n", sda, scl, info->bitrate);
|
||||
} else {
|
||||
checkError("jshI2CSetup",err);
|
||||
}
|
||||
}
|
||||
|
||||
void jshI2CWrite(IOEventFlags device,
|
||||
unsigned char address,
|
||||
int nBytes,
|
||||
const unsigned char *data,
|
||||
bool sendStop) {
|
||||
|
||||
int i2c_master_port = getI2cFromDevice(device);
|
||||
if (i2c_master_port == -1) {
|
||||
jsError("Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
}
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
ret=i2c_master_start(cmd);
|
||||
ret=i2c_master_write_byte(cmd, address << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
ret=i2c_master_write(cmd, data, nBytes, ACK_CHECK_EN);
|
||||
if ( sendStop ) ret=i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(i2c_master_port, cmd, 1000 / portTICK_RATE_MS); // 1000 seems very large for ticks_to_wait???
|
||||
i2c_cmd_link_delete(cmd);
|
||||
checkError( "jshI2CWrite", ret);
|
||||
}
|
||||
|
||||
void jshI2CRead(IOEventFlags device,
|
||||
unsigned char address,
|
||||
int nBytes,
|
||||
unsigned char *data,
|
||||
bool sendStop) {
|
||||
|
||||
if (nBytes <= 0) {
|
||||
return;
|
||||
}
|
||||
int i2c_master_port = getI2cFromDevice(device);
|
||||
if (i2c_master_port == -1) {
|
||||
jsError("Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
}
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
ret=i2c_master_start(cmd);
|
||||
ret=i2c_master_write_byte(cmd, ( i2c_master_port << 1 ) | I2C_MASTER_READ, ACK_CHECK_EN);
|
||||
if (nBytes > 1) {
|
||||
ret=i2c_master_read(cmd, data, nBytes - 1, ACK_VAL);
|
||||
}
|
||||
ret=i2c_master_read_byte(cmd, data + nBytes - 1, NACK_VAL);
|
||||
if ( sendStop ) ret=i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(i2c_master_port, cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
checkError( "jshI2CRead", ret);
|
||||
}
|
||||
27
targets/esp32/i2c.h
Normal file
27
targets/esp32/i2c.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is designed to support i2c functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Rhys Williams (wilberforce)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jspininfo.h"
|
||||
#include "jshardware.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
// Convert an Espruino pin to an ESP32 pin number.
|
||||
gpio_num_t pinToESP32Pin(Pin pin);
|
||||
|
||||
void jshI2CSetup(IOEventFlags device, JshI2CInfo *info);
|
||||
void jshI2CWrite(IOEventFlags device, unsigned char address, int nBytes, const unsigned char *data, bool sendStop);
|
||||
void jshI2CRead(IOEventFlags device, unsigned char address, int nBytes, unsigned char *data, bool sendStop);
|
||||
687
targets/esp32/jshardware.c
Normal file
687
targets/esp32/jshardware.c
Normal file
@ -0,0 +1,687 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2015 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The ESP32 must implement its part of the Espruino contract. This file
|
||||
* provides implementations for interfaces that are expected to be provided
|
||||
* by an Espruino board. The signatures of the exposed functions are part
|
||||
* of the Espruino environment and can not be changed without express
|
||||
* approval from all the stakeholders. In addition, the semantics of the
|
||||
* functions should follow the expected conventions.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "jshardware.h"
|
||||
#include "jshardwareUart.h"
|
||||
#include "jshardwareAnalog.h"
|
||||
#include "jshardwareTimer.h"
|
||||
#include "jshardwarePWM.h"
|
||||
#include "jshardwarePulse.h"
|
||||
|
||||
#include "jsutils.h"
|
||||
#include "jstimer.h"
|
||||
#include "jsparse.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "jspininfo.h"
|
||||
|
||||
#include "jswrap_esp32_network.h"
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/uart.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "i2c.h"
|
||||
#include "spi.h"
|
||||
|
||||
#define FLASH_MAX (4*1024*1024) //4MB
|
||||
#define FLASH_PAGE_SHIFT 12 // Shift is much faster than division by 4096 (size of page)
|
||||
#define FLASH_PAGE ((uint32_t)1<<FLASH_PAGE_SHIFT) //4KB
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
/**
|
||||
* Convert a pin id to the corresponding Pin Event id.
|
||||
*/
|
||||
static IOEventFlags pinToEV_EXTI(
|
||||
Pin pin // !< The pin to map to the event id.
|
||||
) {
|
||||
// Map pin 0 to EV_EXTI0
|
||||
// Map pin 1 to EV_EXTI1
|
||||
// ...
|
||||
// Map pin x to ECEXTIx
|
||||
return (IOEventFlags)(EV_EXTI0 + pin);
|
||||
}
|
||||
|
||||
static uint8_t g_pinState[JSH_PIN_COUNT];
|
||||
|
||||
/**
|
||||
* interrupt handler for gpio interrupts
|
||||
*/
|
||||
void IRAM_ATTR gpio_intr_handler(void* arg){
|
||||
//GPIO intr process. Mainly copied from esp-idf
|
||||
UNUSED(arg);
|
||||
IOEventFlags exti;
|
||||
Pin gpio_num = 0;
|
||||
uint32_t gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG); //read status to get interrupt status for GPIO0-31
|
||||
uint32_t gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);//read status1 to get interrupt status for GPIO32-39
|
||||
SET_PERI_REG_MASK(GPIO_STATUS_W1TC_REG, gpio_intr_status); //Clear intr for gpio0-gpio31
|
||||
SET_PERI_REG_MASK(GPIO_STATUS1_W1TC_REG, gpio_intr_status_h); //Clear intr for gpio32-39
|
||||
do {
|
||||
g_pinState[gpio_num] = 0;
|
||||
if(gpio_num < 32) {
|
||||
if(gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
|
||||
exti = pinToEV_EXTI(gpio_num);
|
||||
jshPushIOWatchEvent(exti);
|
||||
}
|
||||
} else {
|
||||
if(gpio_intr_status_h & BIT(gpio_num - 32)) {
|
||||
exti = pinToEV_EXTI(gpio_num);
|
||||
jshPushIOWatchEvent(exti);
|
||||
}
|
||||
}
|
||||
} while(++gpio_num < GPIO_PIN_COUNT);
|
||||
}
|
||||
|
||||
void jshPinSetStateRange( Pin start, Pin end, JshPinState state ) {
|
||||
for ( Pin p=start; p<=end; p++ ) {
|
||||
jshPinSetState(p, state);
|
||||
}
|
||||
}
|
||||
|
||||
void jshPinDefaultPullup() {
|
||||
// 6-11 are used by Flash chip
|
||||
// 32-33 are routed to rtc for xtal
|
||||
jshPinSetStateRange(0,0,JSHPINSTATE_GPIO_IN_PULLUP);
|
||||
jshPinSetStateRange(12,19,JSHPINSTATE_GPIO_IN_PULLUP);
|
||||
jshPinSetStateRange(21,22,JSHPINSTATE_GPIO_IN_PULLUP);
|
||||
jshPinSetStateRange(25,27,JSHPINSTATE_GPIO_IN_PULLUP);
|
||||
jshPinSetStateRange(34,39,JSHPINSTATE_GPIO_IN_PULLUP);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the JavaScript hardware interface.
|
||||
*/
|
||||
void jshInit() {
|
||||
uint32_t freeHeapSize = esp_get_free_heap_size();
|
||||
jsWarn( "Free heap size: %d", freeHeapSize);
|
||||
esp32_wifi_init();
|
||||
//jswrap_ESP32_wifi_soft_init();
|
||||
jshInitDevices();
|
||||
if (JSHPINSTATE_I2C != 13 || JSHPINSTATE_GPIO_IN_PULLDOWN != 6 || JSHPINSTATE_MASK != 15) {
|
||||
jsError("JshPinState #defines have changed, please update pinStateToString()");
|
||||
}
|
||||
/*
|
||||
jsWarn( "JSHPINSTATE_I2C %d\n",JSHPINSTATE_I2C );
|
||||
jsWarn( "JSHPINSTATE_GPIO_IN_PULLDOWN %d\n",JSHPINSTATE_GPIO_IN_PULLDOWN );
|
||||
jsWarn( "JSHPINSTATE_MASK %d\n",JSHPINSTATE_MASK );
|
||||
*/
|
||||
gpio_isr_register(gpio_intr_handler,NULL,0,NULL); //changed to automatic assign of interrupt
|
||||
// Initialize something for each of the possible pins.
|
||||
jshPinDefaultPullup();
|
||||
} // End of jshInit
|
||||
|
||||
/**
|
||||
* Reset the Espruino environment.
|
||||
*/
|
||||
void jshReset() {
|
||||
jshResetDevices();
|
||||
jshPinDefaultPullup() ;
|
||||
jsWarn("jshReset(): To implement - reset of i2c and SPI\n");
|
||||
jsWarn(">> jshReset()\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-init the ESP32 after a soft-reset
|
||||
*/
|
||||
void jshSoftInit() {
|
||||
jsWarn(">> jshSoftInit()\n");
|
||||
jswrap_ESP32_wifi_soft_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle whatever needs to be done in the idle loop when there's nothing to do.
|
||||
*
|
||||
* Nothing is needed on the ESP32.
|
||||
*/
|
||||
void jshIdle() {
|
||||
|
||||
}
|
||||
|
||||
// ESP32 chips don't have a serial number but they do have a MAC address
|
||||
int jshGetSerialNumber(unsigned char *data, int maxChars) {
|
||||
assert(maxChars >= 6); // it's 32
|
||||
esp_wifi_get_mac(WIFI_IF_STA, data);
|
||||
return 6;
|
||||
}
|
||||
|
||||
//===== Interrupts and sleeping
|
||||
//Mux to protect the JshInterrupt status
|
||||
//static portMUX_TYPE xJshInterrupt = portMUX_INITIALIZER_UNLOCKED;
|
||||
void jshInterruptOff() {
|
||||
//xTaskResumeAll();
|
||||
//taskEXIT_CRITICAL(&xJshInterrupt);
|
||||
taskDISABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
void jshInterruptOn() {
|
||||
//taskENTER_CRITICAL(&xJshInterrupt);
|
||||
taskENABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
/// Enter simple sleep mode (can be woken up by interrupts). Returns true on success
|
||||
bool jshSleep(JsSysTime timeUntilWake) {
|
||||
UNUSED(timeUntilWake);
|
||||
return true;
|
||||
} // End of jshSleep
|
||||
|
||||
|
||||
/**
|
||||
* Delay (blocking) for the supplied number of microseconds.
|
||||
*/
|
||||
void jshDelayMicroseconds(int microsec) {
|
||||
ets_delay_us(microsec);
|
||||
} // End of jshDelayMicroseconds
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the state of the specific pin.
|
||||
*
|
||||
* The possible states are:
|
||||
*
|
||||
* JSHPINSTATE_UNDEFINED
|
||||
* JSHPINSTATE_GPIO_OUT
|
||||
* JSHPINSTATE_GPIO_OUT_OPENDRAIN
|
||||
* JSHPINSTATE_GPIO_OUT_OPENDRAIN_PULLUP
|
||||
* JSHPINSTATE_GPIO_IN
|
||||
* JSHPINSTATE_GPIO_IN_PULLUP
|
||||
* JSHPINSTATE_GPIO_IN_PULLDOWN
|
||||
* JSHPINSTATE_ADC_IN
|
||||
* JSHPINSTATE_AF_OUT
|
||||
* JSHPINSTATE_AF_OUT_OPENDRAIN
|
||||
* JSHPINSTATE_USART_IN
|
||||
* JSHPINSTATE_USART_OUT
|
||||
* JSHPINSTATE_DAC_OUT
|
||||
* JSHPINSTATE_I2C
|
||||
*
|
||||
* This function is exposed indirectly through the exposed global function called
|
||||
* `pinMode()`. For example, `pinMode(pin, "input")` will set the given pin to input.
|
||||
*/
|
||||
void jshPinSetState(
|
||||
Pin pin, //!< The pin to have its state changed.
|
||||
JshPinState state //!< The new desired state of the pin.
|
||||
) {
|
||||
gpio_mode_t mode;
|
||||
gpio_pull_mode_t pull_mode=GPIO_FLOATING;
|
||||
switch(state) {
|
||||
case JSHPINSTATE_GPIO_OUT:
|
||||
mode = GPIO_MODE_INPUT_OUTPUT;
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_IN:
|
||||
mode = GPIO_MODE_INPUT;
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_IN_PULLUP:
|
||||
mode = GPIO_MODE_INPUT;
|
||||
pull_mode=GPIO_PULLUP_ONLY;
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_IN_PULLDOWN:
|
||||
mode = GPIO_MODE_INPUT;
|
||||
pull_mode=GPIO_PULLDOWN_ONLY;
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_OUT_OPENDRAIN:
|
||||
mode = GPIO_MODE_INPUT_OUTPUT_OD;
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_OUT_OPENDRAIN_PULLUP:
|
||||
mode = GPIO_MODE_INPUT_OUTPUT_OD;
|
||||
pull_mode=GPIO_PULLUP_ONLY;
|
||||
break;
|
||||
default:
|
||||
jsError( "jshPinSetState: Unexpected state: %d", state);
|
||||
return;
|
||||
}
|
||||
gpio_num_t gpioNum = pinToESP32Pin(pin);
|
||||
gpio_set_direction(gpioNum, mode);
|
||||
gpio_set_pull_mode(gpioNum, pull_mode);
|
||||
gpio_pad_select_gpio(gpioNum);
|
||||
g_pinState[pin] = state; // remember what we set this to...
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current state of the selected pin.
|
||||
* \return The current state of the selected pin.
|
||||
*/
|
||||
JshPinState jshPinGetState(Pin pin) {
|
||||
if ( jshPinGetValue(pin) & 1 )
|
||||
return g_pinState[pin] | JSHPINSTATE_PIN_IS_ON;
|
||||
return g_pinState[pin];
|
||||
}
|
||||
|
||||
//===== GPIO and PIN stuff =====
|
||||
|
||||
/**
|
||||
* Set the value of the corresponding pin.
|
||||
*/
|
||||
void jshPinSetValue(
|
||||
Pin pin, //!< The pin to have its value changed.
|
||||
bool value //!< The new value of the pin.
|
||||
) {
|
||||
gpio_num_t gpioNum = pinToESP32Pin(pin);
|
||||
gpio_set_level(gpioNum, (uint32_t)value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the corresponding pin.
|
||||
* \return The current value of the pin.
|
||||
*/
|
||||
bool CALLED_FROM_INTERRUPT jshPinGetValue( // can be called at interrupt time
|
||||
Pin pin //!< The pin to have its value read.
|
||||
) {
|
||||
gpio_num_t gpioNum = pinToESP32Pin(pin);
|
||||
bool level = gpio_get_level(gpioNum);
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
JsVarFloat jshPinAnalog(Pin pin) {
|
||||
return (JsVarFloat) readADC(pin) / 4096;
|
||||
}
|
||||
|
||||
|
||||
int jshPinAnalogFast(Pin pin) {
|
||||
return readADC(pin) << 4;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the output PWM value.
|
||||
*/
|
||||
JshPinFunction jshPinAnalogOutput(Pin pin,
|
||||
JsVarFloat value,
|
||||
JsVarFloat freq,
|
||||
JshAnalogOutputFlags flags) { // if freq<=0, the default is used
|
||||
UNUSED(flags);
|
||||
if(pin == 25 || pin == 26){
|
||||
value = (value * 256);
|
||||
uint8_t val8 = value;
|
||||
writeDAC(pin,val8);
|
||||
}
|
||||
else{
|
||||
value = (value * PWMTimerRange);
|
||||
uint16_t val16 = value;
|
||||
writePWM(pin,val16,(int) freq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void jshSetOutputValue(JshPinFunction func, int value) {
|
||||
int pin;
|
||||
if (JSH_PINFUNCTION_IS_DAC(func)) {
|
||||
uint8_t val = (uint8_t)(value >> 8);
|
||||
switch (func & JSH_MASK_INFO) {
|
||||
case JSH_DAC_CH1: writeDAC(25,val); break;
|
||||
case JSH_DAC_CH2: writeDAC(26,val); break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pin = ((func >> JSH_SHIFT_INFO) << 4) + ((func >> JSH_SHIFT_TYPE) & 15);
|
||||
value >> (16 - PWMTimerBit);
|
||||
setPWM(pin,value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void jshEnableWatchDog(JsVarFloat timeout) {
|
||||
UNUSED(timeout);
|
||||
jsError(">> jshEnableWatchDog Not implemented,using taskwatchdog from RTOS");
|
||||
}
|
||||
|
||||
|
||||
// Kick the watchdog
|
||||
void jshKickWatchDog() {
|
||||
jsError(">> jshKickWatchDog Not implemented,using taskwatchdog from RTOS");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the state of the pin associated with the event flag.
|
||||
*/
|
||||
bool CALLED_FROM_INTERRUPT jshGetWatchedPinState(IOEventFlags eventFlag) { // can be called at interrupt time
|
||||
gpio_num_t gpioNum = pinToESP32Pin((Pin)(eventFlag-EV_EXTI0));
|
||||
bool level = gpio_get_level(gpioNum);
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the pin to be the value supplied and then wait for
|
||||
* a given period and set the pin value again to be the opposite.
|
||||
*/
|
||||
void jshPinPulse(
|
||||
Pin pin, //!< The pin to be pulsed.
|
||||
bool pulsePolarity, //!< The value to be pulsed into the pin.
|
||||
JsVarFloat pulseTime //!< The duration in milliseconds to hold the pin.
|
||||
) {
|
||||
int duration = (int)pulseTime * 1000; //from millisecs to microsecs
|
||||
sendPulse(pin, pulsePolarity, duration);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the pin can be watchable.
|
||||
* \return Returns true if the pin is wathchable.
|
||||
*/
|
||||
bool jshCanWatch(
|
||||
Pin pin //!< The pin that we are asking whether or not we can watch it.
|
||||
) {
|
||||
UNUSED(pin);
|
||||
return true; //lets assume all pins will do
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do what ever is necessary to watch a pin.
|
||||
* \return The event flag for this pin.
|
||||
*/
|
||||
IOEventFlags jshPinWatch(
|
||||
Pin pin, //!< The pin to be watched.
|
||||
bool shouldWatch //!< True for watching and false for unwatching.
|
||||
) {
|
||||
gpio_num_t gpioNum = pinToESP32Pin(pin);
|
||||
if(shouldWatch){
|
||||
gpio_set_intr_type(gpioNum,GPIO_INTR_ANYEDGE); //set posedge interrupt
|
||||
gpio_set_direction(gpioNum,GPIO_MODE_INPUT); //set as input
|
||||
gpio_set_pull_mode(gpioNum,GPIO_PULLUP_ONLY); //enable pull-up mode
|
||||
gpio_intr_enable(gpioNum); //enable interrupt
|
||||
}
|
||||
else{
|
||||
if(gpio_intr_disable(gpioNum) == ESP_ERR_INVALID_ARG){ //disable interrupt
|
||||
jsError("*** jshPinWatch error");
|
||||
}
|
||||
}
|
||||
return pin;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
JshPinFunction jshGetCurrentPinFunction(Pin pin) {
|
||||
if (jshIsPinValid(pin)) {
|
||||
int i;
|
||||
for (i=0;i<JSH_PININFO_FUNCTIONS;i++) {
|
||||
JshPinFunction func = pinInfo[pin].functions[i];
|
||||
if (JSH_PINFUNCTION_IS_TIMER(func) ||
|
||||
JSH_PINFUNCTION_IS_DAC(func))
|
||||
return func;
|
||||
}
|
||||
}
|
||||
return JSH_NOTHING;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a given event is associated with a given pin.
|
||||
* \return True if the event is associated with the pin and false otherwise.
|
||||
*/
|
||||
bool jshIsEventForPin(
|
||||
IOEvent *event, //!< The event that has been detected.
|
||||
Pin pin //!< The identity of a pin.
|
||||
) {
|
||||
return IOEVENTFLAGS_GETTYPE(event->flags) == pinToEV_EXTI(pin);
|
||||
}
|
||||
|
||||
//===== USART and Serial =====
|
||||
|
||||
|
||||
|
||||
void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
|
||||
initSerial(device,inf);
|
||||
}
|
||||
|
||||
bool jshIsUSBSERIALConnected() {
|
||||
return false; // "On non-USB boards this just returns false"
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick a device into action (if required).
|
||||
*
|
||||
*/
|
||||
void jshUSARTKick(
|
||||
IOEventFlags device //!< The device to be kicked.
|
||||
) {
|
||||
int c = jshGetCharToTransmit(device);
|
||||
while(c >= 0) {
|
||||
if(device == EV_SERIAL1) uart_tx_one_char((uint8_t)c);
|
||||
else writeSerial(device,(uint8_t)c);
|
||||
c = jshGetCharToTransmit(device);
|
||||
}
|
||||
}
|
||||
|
||||
//===== System time stuff =====
|
||||
|
||||
/**
|
||||
* Given a time in milliseconds as float, get us the value in microsecond
|
||||
*/
|
||||
JsSysTime jshGetTimeFromMilliseconds(JsVarFloat ms) {
|
||||
return (JsSysTime) (ms * 1000.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a time in microseconds, get us the value in milliseconds (float)
|
||||
*/
|
||||
JsVarFloat jshGetMillisecondsFromTime(JsSysTime time) {
|
||||
return (JsVarFloat) time / 1000.0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current time in microseconds.
|
||||
*/
|
||||
JsSysTime CALLED_FROM_INTERRUPT jshGetSystemTime() { // in us -- can be called at interrupt time
|
||||
struct timeval tm;
|
||||
gettimeofday(&tm, 0);
|
||||
return (JsSysTime)(tm.tv_sec)*1000000L + tm.tv_usec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current time in microseconds.
|
||||
*/
|
||||
void jshSetSystemTime(JsSysTime newTime) {
|
||||
struct timeval tm;
|
||||
struct timezone tz;
|
||||
|
||||
tm.tv_sec=(time_t)(newTime/1000000L);
|
||||
tm.tv_usec=0;
|
||||
tz.tz_minuteswest=0;
|
||||
tz.tz_dsttime=0;
|
||||
settimeofday(&tm, &tz);
|
||||
}
|
||||
|
||||
void jshUtilTimerDisable() {
|
||||
disableTimer(0);
|
||||
}
|
||||
|
||||
void jshUtilTimerStart(JsSysTime period) {
|
||||
startTimer(0,(uint64_t) period);
|
||||
}
|
||||
|
||||
void jshUtilTimerReschedule(JsSysTime period) {
|
||||
rescheduleTimer(0,(uint64_t) period);
|
||||
}
|
||||
|
||||
//===== Miscellaneous =====
|
||||
|
||||
static uint64_t DEVICE_INITIALISED_FLAGS = 0L;
|
||||
bool jshIsDeviceInitialised(IOEventFlags device) {
|
||||
uint64_t mask = 1ULL << (int)device;
|
||||
return (DEVICE_INITIALISED_FLAGS & mask) != 0L;
|
||||
|
||||
// UNUSED(device);
|
||||
// jsError(">> jshIsDeviceInitialised not implemented");
|
||||
// return 0;
|
||||
} // End of jshIsDeviceInitialised
|
||||
|
||||
void jshSetDeviceInitialised(IOEventFlags device, bool isInit) {
|
||||
uint64_t mask = 1ULL << (int)device;
|
||||
if (isInit) {
|
||||
DEVICE_INITIALISED_FLAGS |= mask;
|
||||
} else {
|
||||
DEVICE_INITIALISED_FLAGS &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
// the esp32 temperature sensor - undocumented library function call. Unsure of values returned.
|
||||
JsVarFloat jshReadTemperature() {
|
||||
extern uint8_t temprature_sens_read();
|
||||
return temprature_sens_read();
|
||||
}
|
||||
|
||||
// the esp8266 can read the VRef but then there's no analog input, so we don't support this
|
||||
JsVarFloat jshReadVRef() {
|
||||
jsError(">> jshReadVRef Not implemented");
|
||||
return NAN;
|
||||
}
|
||||
|
||||
unsigned int jshGetRandomNumber() {
|
||||
return (unsigned int)rand();
|
||||
}
|
||||
|
||||
//===== Read-write flash =====
|
||||
|
||||
/**
|
||||
* Determine available flash depending on EEprom size
|
||||
*
|
||||
*/
|
||||
uint32_t jshFlashMax() {
|
||||
return (FLASH_MAX-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from flash memory into the buffer.
|
||||
*
|
||||
* This reads from flash using memory-mapped reads. Only works for the first 1MB and
|
||||
* requires 4-byte aligned reads.
|
||||
*
|
||||
*/
|
||||
void jshFlashRead(
|
||||
void *buf, //!< buffer to read into
|
||||
uint32_t addr, //!< Flash address to read from
|
||||
uint32_t len //!< Length of data to read
|
||||
) {
|
||||
|
||||
if(len == 1){ // Can't read a single byte using the API, so read 4 and select the byte requested
|
||||
uint word;
|
||||
spi_flash_read(addr & 0xfffffffc,&word,4);
|
||||
*(uint8_t *)buf = (word >> ((addr & 3) << 3 )) & 255;
|
||||
}
|
||||
else spi_flash_read(addr, buf, len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write data to flash memory from the buffer.
|
||||
*
|
||||
* This is called from jswrap_flash_write and ... which guarantee that addr is 4-byte aligned
|
||||
* and len is a multiple of 4.
|
||||
*/
|
||||
void jshFlashWrite(
|
||||
void *buf, //!< Buffer to write from
|
||||
uint32_t addr, //!< Flash address to write into
|
||||
uint32_t len //!< Length of data to write
|
||||
) {
|
||||
spi_flash_write(addr, buf, len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return start address and size of the flash page the given address resides in.
|
||||
* Returns false if no page.
|
||||
*/
|
||||
bool jshFlashGetPage(
|
||||
uint32_t addr, //!<
|
||||
uint32_t *startAddr, //!<
|
||||
uint32_t *pageSize //!<
|
||||
) {
|
||||
if (addr >= FLASH_MAX) return false;
|
||||
*startAddr = addr & ~(FLASH_PAGE-1);
|
||||
*pageSize = FLASH_PAGE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void addFlashArea(JsVar *jsFreeFlash, uint32_t addr, uint32_t length) {
|
||||
JsVar *jsArea = jsvNewObject();
|
||||
if (!jsArea) return;
|
||||
jsvObjectSetChildAndUnLock(jsArea, "addr", jsvNewFromInteger((JsVarInt)addr));
|
||||
jsvObjectSetChildAndUnLock(jsArea, "length", jsvNewFromInteger((JsVarInt)length));
|
||||
jsvArrayPushAndUnLock(jsFreeFlash, jsArea);
|
||||
}
|
||||
|
||||
JsVar *jshFlashGetFree() {
|
||||
JsVar *jsFreeFlash = jsvNewEmptyArray();
|
||||
if (!jsFreeFlash) return 0;
|
||||
// Space should be reserved here in the parition table - assume 4Mb EEPROM
|
||||
// Set just after programme save area
|
||||
addFlashArea(jsFreeFlash, 0x100000 + FLASH_PAGE * 16, 0x300000-FLASH_PAGE * 16-1);
|
||||
|
||||
return jsFreeFlash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Erase the flash page containing the address.
|
||||
*/
|
||||
void jshFlashErasePage(
|
||||
uint32_t addr //!<
|
||||
) {
|
||||
spi_flash_erase_sector(addr >> FLASH_PAGE_SHIFT);
|
||||
}
|
||||
|
||||
unsigned int jshSetSystemClock(JsVar *options) {
|
||||
UNUSED(options);
|
||||
jsError(">> jshSetSystemClock Not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an Espruino pin id to a native ESP32 pin id.
|
||||
*/
|
||||
gpio_num_t pinToESP32Pin(Pin pin) {
|
||||
if ( pin < 40 )
|
||||
return pin + GPIO_NUM_0;
|
||||
jsError( "pinToESP32Pin: Unknown pin: %d", pin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool jshNeopixelWrite(Pin pin, unsigned char *rgbData, size_t rgbSize) {
|
||||
jsExceptionHere(JSET_ERROR, "Neopixel writing not implemented");
|
||||
return false;
|
||||
}
|
||||
131
targets/esp32/jshardwareAnalog.c
Normal file
131
targets/esp32/jshardwareAnalog.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is designed to support Analog functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "jshardwareAnalog.h"
|
||||
#include "driver/adc.h"
|
||||
#include "driver/dac.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define adc_channel_max 8
|
||||
|
||||
adc_atten_t adc_channel[8];
|
||||
|
||||
adc1_channel_t pinToAdcChannel(Pin pin){
|
||||
adc1_channel_t channel;
|
||||
switch(pin){
|
||||
case 36: channel = ADC1_CHANNEL_0; break;
|
||||
case 37: channel = ADC1_CHANNEL_1; break;
|
||||
case 38: channel = ADC1_CHANNEL_2; break;
|
||||
case 39: channel = ADC1_CHANNEL_3; break;
|
||||
case 32: channel = ADC1_CHANNEL_4; break;
|
||||
case 33: channel = ADC1_CHANNEL_5; break;
|
||||
case 34: channel = ADC1_CHANNEL_6; break;
|
||||
case 35: channel = ADC1_CHANNEL_7; break;
|
||||
default: channel = -1; break;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
adc_atten_t rangeToAdcAtten(int range){
|
||||
adc_atten_t atten;
|
||||
switch (range){
|
||||
case 1000: atten = ADC_ATTEN_0db; break;
|
||||
case 1340: atten = ADC_ATTEN_2_5db; break;
|
||||
case 2000: atten = ADC_ATTEN_6db; break;
|
||||
case 3600: atten = ADC_ATTEN_11db; break;
|
||||
default: atten = ADC_ATTEN_11db; break;
|
||||
}
|
||||
return atten;
|
||||
}
|
||||
int pinToAdcChannelIdx(Pin pin){
|
||||
int idx;
|
||||
switch(pin){
|
||||
case 36: idx = 0;break;
|
||||
case 37: idx = 1;break;
|
||||
case 38: idx = 2;break;
|
||||
case 39: idx = 3;break;
|
||||
case 32: idx = 4;break;
|
||||
case 33: idx = 5;break;
|
||||
case 34: idx = 6;break;
|
||||
case 35: idx = 7;break;
|
||||
default: idx = -1; break;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
dac_channel_t pinToDacChannel(Pin pin){
|
||||
dac_channel_t channel;
|
||||
switch(pin){
|
||||
case 25: channel = DAC_CHANNEL_1; break;
|
||||
case 26: channel = DAC_CHANNEL_2; break;
|
||||
default: channel = -1; break;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
void initADC(int ADCgroup){
|
||||
switch(ADCgroup){
|
||||
case 1:
|
||||
adc1_config_width(ADC_WIDTH_12Bit);
|
||||
for(int i = 0; i < adc_channel_max; i++){ adc_channel[i] = ADC_ATTEN_11db; }
|
||||
break;
|
||||
case 2:
|
||||
jsExceptionHere(JSET_ERROR, "not implemented\n");
|
||||
break;
|
||||
case 3:
|
||||
jsExceptionHere(JSET_ERROR, "not implemented\n");
|
||||
break;
|
||||
default:
|
||||
jsExceptionHere(JSET_ERROR, "out of range\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rangeADC(Pin pin,int range){
|
||||
int idx,atten;
|
||||
idx = pinToAdcChannelIdx(pin);
|
||||
printf("idx:%d\n",idx);
|
||||
if(idx >= 0){
|
||||
adc_channel[idx] = rangeToAdcAtten(range);
|
||||
printf("Atten:%d \n",adc_channel[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
int readADC(Pin pin){
|
||||
adc1_channel_t channel; int value;
|
||||
channel = pinToAdcChannel(pin);
|
||||
adc1_config_channel_atten(channel,adc_channel[pinToAdcChannelIdx(pin)]);
|
||||
if(channel >= 0) {
|
||||
value = adc1_get_voltage(channel);
|
||||
return value;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void writeDAC(Pin pin,uint8_t value){
|
||||
dac_channel_t channel;
|
||||
if(value > 255){
|
||||
jsExceptionHere(JSET_ERROR, "not implemented, only 8 bit supported\n");
|
||||
return;
|
||||
}
|
||||
channel = pinToDacChannel(pin);
|
||||
if(channel >= 0) dac_out_voltage(channel, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
24
targets/esp32/jshardwareAnalog.h
Normal file
24
targets/esp32/jshardwareAnalog.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is designed to support Analog functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jspininfo.h"
|
||||
|
||||
void initADC(int ADCgroup);
|
||||
int readADC(Pin pin);
|
||||
void rangeADC(Pin pin,int range);
|
||||
|
||||
void writeDAC(Pin pin,uint8_t value);
|
||||
122
targets/esp32/jshardwarePWM.c
Normal file
122
targets/esp32/jshardwarePWM.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* This file is designed to support PWM functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "esp_log.h"
|
||||
#include "jsutils.h"
|
||||
|
||||
#include "jshardwarePWM.h"
|
||||
#include "driver/ledc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define PWMFreqDefault 5000
|
||||
#define PWMPinEmpty 111
|
||||
#define PWMTimerDefault 3
|
||||
|
||||
int getTimerIndex(Pin pin,int freq){
|
||||
int i;
|
||||
for(i = 0; i < PWMFreqMax; i++){
|
||||
if(PWMFreqChannels[i].pin == pin) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int getFreeTimer(Pin pin,int freq){
|
||||
int i;
|
||||
i = getTimerIndex(pin,freq);
|
||||
if(i >= 0) return i;
|
||||
for(i = 0; i < PWMFreqMax; i++){
|
||||
if(PWMFreqChannels[i].pin == PWMPinEmpty) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getChannelIndex(Pin pin){
|
||||
int i;
|
||||
for(i = 0; i < PWMMax; i++){
|
||||
if(PWMChannels[i].pin == pin) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int getFreeChannel(pin){
|
||||
int i;
|
||||
i = getChannelIndex(pin);
|
||||
if(i >= 0) return i;
|
||||
for(i = 0; i < PWMMax; i++){
|
||||
if(PWMChannels[i].pin == PWMPinEmpty) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void timerConfig(int freq,int timer){
|
||||
ledc_timer_config_t PWM_timer = {
|
||||
.bit_num = LEDC_TIMER_10_BIT,//set timer counter bit number
|
||||
.freq_hz = freq,//set frequency of pwm
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,//timer mode,
|
||||
.timer_num = timer//timer index
|
||||
};
|
||||
ledc_timer_config(&PWM_timer);
|
||||
}
|
||||
void channelConfig(int timer, int channel, int value, Pin pin){
|
||||
ledc_channel_config_t PWM_channel = {
|
||||
.channel = channel,//set LEDC channel 0
|
||||
.duty = value,//set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1)
|
||||
.gpio_num = pin,//GPIO number
|
||||
.intr_type = LEDC_INTR_DISABLE,//GPIO INTR TYPE, as an example, we enable fade_end interrupt here.
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,//set LEDC mode, from ledc_mode_t
|
||||
.timer_sel = timer
|
||||
};
|
||||
ledc_channel_config(&PWM_channel);
|
||||
}
|
||||
|
||||
void PWMInit(){
|
||||
int i;
|
||||
timerConfig(PWMFreqDefault,PWMTimerDefault);
|
||||
for(i = 0; i < PWMMax; i++) PWMChannels[i].pin = PWMPinEmpty;
|
||||
for(i = 0; i < PWMFreqMax; i++) PWMFreqChannels[i].pin = PWMPinEmpty;
|
||||
}
|
||||
|
||||
void writePWM(Pin pin,uint16_t value,int freq){
|
||||
int channel; int timer;
|
||||
if(freq == PWMFreqDefault || freq == 0){
|
||||
channel = getFreeChannel(pin);
|
||||
if(channel < 0){jsError("no PWM channel available anymore");}
|
||||
else{
|
||||
PWMChannels[channel].pin = pin;
|
||||
channelConfig(PWMTimerDefault,channel,value,pin);
|
||||
}
|
||||
}
|
||||
else{
|
||||
timer = getFreeTimer(pin,freq);
|
||||
if(timer < 0){jsError("no PWM channel available anymore");}
|
||||
else{
|
||||
PWMFreqChannels[timer].pin = pin;
|
||||
PWMFreqChannels[timer].freq = freq;
|
||||
timerConfig(freq,timer);
|
||||
channelConfig(timer,PWMMax + timer,value,pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setPWM(Pin pin,uint16_t value){
|
||||
int channel = getChannelIndex(pin);
|
||||
if(channel < 0){jsError("pin not assigned to pwm");}
|
||||
else{
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, channel, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
33
targets/esp32/jshardwarePWM.h
Normal file
33
targets/esp32/jshardwarePWM.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is designed to support PWM functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jspininfo.h"
|
||||
|
||||
#define PWMMax 5 //maximum PWM channel for Analog output (freq = 50000)
|
||||
#define PWMFreqMax 3 //maximum PWM channel with free frequency
|
||||
#define PWMTimerBit 10 //10 bit for value
|
||||
#define PWMTimerRange 1024
|
||||
|
||||
struct PWMChannel{Pin pin;}; //will be extended once we know more about PWM for Espruino on ESP32
|
||||
struct PWMChannel PWMChannels[PWMMax];
|
||||
struct PWMFreqChannel{Pin pin; int freq};
|
||||
struct PWMFreqChannel PWMFreqChannels[PWMFreqMax];
|
||||
|
||||
void PWMInit();
|
||||
void writePWM(Pin pin, uint16_t value,int freq);
|
||||
|
||||
void setPWM(Pin pin,uint16_t value);
|
||||
99
targets/esp32/jshardwarePulse.c
Normal file
99
targets/esp32/jshardwarePulse.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is designed to support Pulse functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "esp_log.h"
|
||||
#include "jsutils.h"
|
||||
|
||||
#include "jshardwarePulse.h"
|
||||
#include "driver/rmt.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define RMTPinEmpty 111
|
||||
|
||||
rmt_item32_t items[1];
|
||||
|
||||
int getRMTIndex(Pin pin){
|
||||
int i;
|
||||
for(i = 0; i < RMTChannelMax; i++){
|
||||
if(RMTChannels[i].pin == pin) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int getFreeRMT(Pin pin){
|
||||
for(int i = 0; i < RMTChannelMax; i++){
|
||||
if(RMTChannels[i].pin == RMTPinEmpty) {
|
||||
RMTChannels[i].pin = pin;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RMTInit(){
|
||||
int i;
|
||||
for(i = 0; i < RMTChannelMax; i++) RMTChannels[i].pin = RMTPinEmpty;
|
||||
}
|
||||
int RMTInitChannel(Pin pin, bool pulsePolarity){
|
||||
rmt_config_t config;
|
||||
int i = getFreeRMT(pin);
|
||||
if(i >= 0){
|
||||
config.rmt_mode = RMT_MODE_TX;
|
||||
config.channel = i;
|
||||
config.gpio_num = pin;
|
||||
config.mem_block_num = 1;
|
||||
config.tx_config.loop_en = 0;
|
||||
config.tx_config.carrier_en = 0;
|
||||
config.tx_config.idle_output_en = 1;
|
||||
if(pulsePolarity) config.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
|
||||
else config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
|
||||
config.tx_config.carrier_duty_percent = 50;
|
||||
config.tx_config.carrier_freq_hz = 10000;
|
||||
config.tx_config.carrier_level = 1;
|
||||
config.clk_div = 80;
|
||||
rmt_config(&config);
|
||||
rmt_driver_install(config.channel, 0, 0);
|
||||
return i;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void setPulseLow(int duration){
|
||||
items[0].duration0 = duration;
|
||||
items[0].level0 = 0;
|
||||
items[0].duration1 = 10;
|
||||
items[0].level1 = 1;
|
||||
}
|
||||
rmt_item32_t *setPulseHigh(int duration){
|
||||
items[0].duration0 = duration;
|
||||
items[0].level0 = 1;
|
||||
items[0].duration1 = 10;
|
||||
items[0].level1 = 0;
|
||||
}
|
||||
|
||||
//pin to be pulsed. value to be pulsed into the pin. duration in milliseconds to hold the pin.
|
||||
void sendPulse(Pin pin, bool pulsePolarity, int duration){
|
||||
int i;
|
||||
i = getRMTIndex(pin);
|
||||
if(i < 0) i = RMTInitChannel(pin,pulsePolarity);
|
||||
if(i >= 0){
|
||||
if(pulsePolarity) setPulseLow(duration);else setPulseHigh(duration);
|
||||
rmt_write_items(i, items,1,1);
|
||||
}
|
||||
else printf("all RMT channels in use\n");
|
||||
return;
|
||||
}
|
||||
|
||||
29
targets/esp32/jshardwarePulse.h
Normal file
29
targets/esp32/jshardwarePulse.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is designed to support Pulse functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jspininfo.h"
|
||||
|
||||
#define RMTChannelMax 8 //maximum RMT channel
|
||||
|
||||
struct RMTChannel{Pin pin;}; //will be extended once we know more about RMT functions for Espruino on ESP32
|
||||
struct RMTChannel RMTChannels[RMTChannelMax];
|
||||
|
||||
void RMTInit();
|
||||
void sendPulse(Pin pin, //!< The pin to be pulsed.
|
||||
bool pulsePolarity, //!< The value to be pulsed into the pin.
|
||||
int duration //!< The duration in microseconds to hold the pin.
|
||||
);
|
||||
44
targets/esp32/jshardwareTimer.c
Normal file
44
targets/esp32/jshardwareTimer.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is designed to support Timer functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "jshardwareTimer.h"
|
||||
#include "rtosutil.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "driver/timer.h"
|
||||
#include "jstimer.h"
|
||||
|
||||
void startTimer(int timer_idx,uint64_t duration){
|
||||
timer_Start(timer_idx,duration);
|
||||
}
|
||||
|
||||
void disableTimer(int timer_idx){
|
||||
timer_disable_intr(TIMER_GROUP_0, timer_idx);
|
||||
}
|
||||
|
||||
void rescheduleTimer(int timer_idx,uint64_t duration){
|
||||
timer_Reschedule(timer_idx,duration);
|
||||
}
|
||||
25
targets/esp32/jshardwareTimer.h
Normal file
25
targets/esp32/jshardwareTimer.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is designed to support Timer functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void initTimer();
|
||||
|
||||
void startTimer(int timer_idx,uint64_t duration);
|
||||
|
||||
void disableTimer(int timer_idx);
|
||||
|
||||
void rescheduleTimer(int timer_idx,uint64_t duration);
|
||||
|
||||
105
targets/esp32/jshardwareUart.c
Normal file
105
targets/esp32/jshardwareUart.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is designed to support FREERTOS functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jshardwareUart.h"
|
||||
#include "driver/uart.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <jsdevices.h>
|
||||
|
||||
bool serial2_initialized = false;
|
||||
bool serial3_initialized = false;
|
||||
|
||||
void initUart(int uart_num,uart_config_t uart_config,int txpin,int rxpin){
|
||||
int r;
|
||||
r = uart_param_config(uart_num, &uart_config); //Configure UART1 parameters
|
||||
r = uart_set_pin(uart_num, txpin, rxpin, -1, -1); //Set UART0 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19)
|
||||
r = uart_driver_install(uart_num, 1024, 1024, 10, NULL, 0); //Install UART driver( We don't need an event queue here)
|
||||
}
|
||||
|
||||
void initSerial(IOEventFlags device,JshUSARTInfo *inf){
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = inf->baudRate,
|
||||
.data_bits = (inf->bytesize == 7)? UART_DATA_7_BITS : UART_DATA_8_BITS,
|
||||
.stop_bits = (inf->stopbits == 1)? UART_STOP_BITS_1 : UART_STOP_BITS_2,
|
||||
//.flow_ctrl = (inf->xOnXOff)? UART_HW_FLOWCTRL_DISABLE : UART_HW_FLOWCTRL_CTS_RTS,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
.parity = UART_PARITY_DISABLE
|
||||
};
|
||||
switch(inf->parity){
|
||||
case 0: uart_config.parity = UART_PARITY_DISABLE; break;
|
||||
case 1: uart_config.parity = UART_PARITY_ODD; break;
|
||||
case 2: uart_config.parity = UART_PARITY_EVEN; break;
|
||||
}
|
||||
if(device == EV_SERIAL1) initUart(uart_console,uart_config,-1,-1);
|
||||
else{
|
||||
if(device == EV_SERIAL2){
|
||||
if(inf->pinTX == 0xff) inf->pinTX = 4;
|
||||
if(inf->pinRX == 0xff) inf->pinRX = 5;
|
||||
if(serial2_initialized) uart_driver_delete(uart_Serial2);
|
||||
initUart(uart_Serial2,uart_config,inf->pinTX,inf->pinRX);
|
||||
serial2_initialized = true;
|
||||
}
|
||||
else{
|
||||
if(inf->pinTX == 0xff) inf->pinTX = 17;
|
||||
if(inf->pinRX == 0xff) inf->pinRX = 16;
|
||||
if(serial3_initialized) uart_driver_delete(uart_Serial3);
|
||||
initUart(uart_Serial3,uart_config,inf->pinTX,inf->pinRX);
|
||||
serial3_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initConsole(){
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
};
|
||||
initUart(uart_console,uart_config,-1,-1);
|
||||
}
|
||||
|
||||
uint8_t rxbuf[256];
|
||||
void consoleToEspruino(){
|
||||
int len = uart_read_bytes(uart_console, rxbuf, sizeof(rxbuf), 100); //Read data from UART
|
||||
if(len > 0) jshPushIOCharEvents(EV_SERIAL1, rxbuf, len);
|
||||
}
|
||||
|
||||
void serialToEspruino(){
|
||||
int len;
|
||||
if(serial2_initialized){
|
||||
len = uart_read_bytes(uart_Serial2,rxbuf, sizeof(rxbuf),0);
|
||||
if(len > 0)jshPushIOCharEvents(EV_SERIAL2, rxbuf, len);
|
||||
}
|
||||
if(serial3_initialized){
|
||||
len = uart_read_bytes(uart_Serial3,rxbuf, sizeof(rxbuf),0);
|
||||
if(len > 0) jshPushIOCharEvents(EV_SERIAL3, rxbuf,len);
|
||||
}
|
||||
}
|
||||
|
||||
void writeSerial(IOEventFlags device,uint8_t c){
|
||||
char str[2]; int r;
|
||||
str[1] = '\0';
|
||||
str[0] = (char)c;
|
||||
if(device == EV_SERIAL2){ r = uart_write_bytes(uart_Serial2, (const char*)str,1);}
|
||||
else{r = uart_write_bytes(uart_Serial3, (const char*)str,1);}
|
||||
}
|
||||
27
targets/esp32/jshardwareUart.h
Normal file
27
targets/esp32/jshardwareUart.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is designed to support UART functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "jshardware.h"
|
||||
|
||||
#define uart_console 0
|
||||
#define uart_Serial2 1
|
||||
#define uart_Serial3 2
|
||||
|
||||
void initConsole();
|
||||
void initSerial(IOEventFlags device,JshUSARTInfo *inf);
|
||||
void writeSerial(IOEventFlags device,uint8_t c);
|
||||
void consoleToEspruino();
|
||||
void serialToEspruino();
|
||||
139
targets/esp32/jswrap_esp32.c
Normal file
139
targets/esp32/jswrap_esp32.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific exposed components.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "jswrap_esp32.h"
|
||||
#include "jshardwareAnalog.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static char *tag = "jswrap_esp32";
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "ESP32",
|
||||
"name" : "setAtten",
|
||||
"generate" : "jswrap_ESP32_setAtten",
|
||||
"params" : [
|
||||
["pin", "pin", "Pin for Analog read"],
|
||||
["atten", "int", "Attenuate factor"]
|
||||
]
|
||||
}*/
|
||||
void jswrap_ESP32_setAtten(Pin pin,int atten){
|
||||
printf("Atten:%d\n",atten);
|
||||
rangeADC(pin, atten);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "ESP32",
|
||||
"name" : "reboot",
|
||||
"generate" : "jswrap_ESP32_reboot"
|
||||
}
|
||||
Perform a hardware reset/reboot of the ESP32.
|
||||
*/
|
||||
void jswrap_ESP32_reboot() {
|
||||
ESP_LOGD(tag, ">> jswrap_ESP32_reboot");
|
||||
esp_restart(); // Call the ESP-IDF to restart the ESP32.
|
||||
ESP_LOGD(tag, "<< jswrap_ESP32_reboot");
|
||||
} // End of jswrap_ESP32_reboot
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "ESP32",
|
||||
"name" : "getState",
|
||||
"generate" : "jswrap_ESP32_getState",
|
||||
"return" : ["JsVar", "The state of the ESP32"]
|
||||
}
|
||||
Returns an object that contains details about the state of the ESP32 with the following fields:
|
||||
|
||||
* `sdkVersion` - Version of the SDK.
|
||||
* `cpuFrequency` - CPU operating frequency in Mhz.
|
||||
* `freeHeap` - Amount of free heap in bytes.
|
||||
* `maxCon` - Maximum number of concurrent connections.
|
||||
* `flashMap` - Configured flash size&map: '512KB:256/256' .. '4MB:512/512'
|
||||
* `flashKB` - Configured flash size in KB as integer
|
||||
* `flashChip` - Type of flash chip as string with manufacturer & chip, ex: '0xEF 0x4016`
|
||||
|
||||
*/
|
||||
JsVar *jswrap_ESP32_getState() {
|
||||
// Create a new variable and populate it with the properties of the ESP32 that we
|
||||
// wish to return.
|
||||
JsVar *esp32State = jsvNewObject();
|
||||
// system_get_sdk_version() - is deprecated , need to find alternative
|
||||
jsvObjectSetChildAndUnLock(esp32State, "sdkVersion", jsvNewFromString("1.0 2016-12-03"));
|
||||
//jsvObjectSetChildAndUnLock(esp32State, "cpuFrequency", jsvNewFromInteger(system_get_cpu_freq()));
|
||||
jsvObjectSetChildAndUnLock(esp32State, "freeHeap", jsvNewFromInteger(esp_get_free_heap_size()));
|
||||
return esp32State;
|
||||
} // End of jswrap_ESP32_getState
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "ESP32",
|
||||
"name" : "setLogLevel",
|
||||
"generate" : "jswrap_ESP32_setLogLevel",
|
||||
"params" : [
|
||||
["tag", "JsVar", "The tag to set logging."],
|
||||
["logLevel", "JsVar", "The log level to set."]
|
||||
]
|
||||
}
|
||||
Set the logLevel for the corresponding debug tag. If tag is `*` then we reset all
|
||||
tags to this logLevel. The logLevel may be one of:
|
||||
* verbose
|
||||
* debug
|
||||
* info
|
||||
* warn
|
||||
* error
|
||||
* none
|
||||
*/
|
||||
/**
|
||||
* The ESP-IDF provides a logging/debug mechanism where logging statements can be inserted
|
||||
* into the code. At run time, the logging levels can be adjusted dynamically through
|
||||
* a call to esp_log_level_set. This allows us to selectively switch on or off
|
||||
* distinct log levels. Imagine a situation where you have no logging (normal status)
|
||||
* and something isn't working as desired. Now what you can do is switch on all logging
|
||||
* or a subset of logging through this JavaScript API.
|
||||
*/
|
||||
void jswrap_ESP32_setLogLevel(JsVar *jsTagToSet, JsVar *jsLogLevel) {
|
||||
char tagToSetStr[20];
|
||||
esp_log_level_t level;
|
||||
|
||||
ESP_LOGD(tag, ">> jswrap_ESP32_setLogLevel");
|
||||
// TODO: Add guards for invalid parameters.
|
||||
jsvGetString(jsTagToSet, tagToSetStr, sizeof(tagToSetStr));
|
||||
|
||||
// Examine the level string and see what kind of level it is.
|
||||
if (jsvIsStringEqual(jsLogLevel, "verbose")) {
|
||||
level = ESP_LOG_VERBOSE;
|
||||
} else if (jsvIsStringEqual(jsLogLevel, "debug")) {
|
||||
level = ESP_LOG_DEBUG;
|
||||
} else if (jsvIsStringEqual(jsLogLevel, "info")) {
|
||||
level = ESP_LOG_INFO;
|
||||
} else if (jsvIsStringEqual(jsLogLevel, "warn")) {
|
||||
level = ESP_LOG_WARN;
|
||||
} else if (jsvIsStringEqual(jsLogLevel, "error")) {
|
||||
level = ESP_LOG_ERROR;
|
||||
} else if (jsvIsStringEqual(jsLogLevel, "none")) {
|
||||
level = ESP_LOG_NONE;
|
||||
} else {
|
||||
ESP_LOGW(tag, "<< jswrap_ESP32_setLogLevel - Unknown log level");
|
||||
return;
|
||||
}
|
||||
esp_log_level_set(tagToSetStr, level); // Call the ESP-IDF to set the log level for the given tag.
|
||||
ESP_LOGD(tag, "<< jswrap_ESP32_setLogLevel");
|
||||
return;
|
||||
} // End of jswrap_ESP32_setLogLevel
|
||||
26
targets/esp32/jswrap_esp32.h
Normal file
26
targets/esp32/jswrap_esp32.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2015 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific function definitions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef TARGETS_ES32_JSWRAP_ESP32_H_
|
||||
#define TARGETS_ESP32_JSWRAP_ESP32_H_
|
||||
#include "jsvar.h"
|
||||
#include "jspin.h"
|
||||
|
||||
//===== ESP32 Library
|
||||
JsVar *jswrap_ESP32_getState();
|
||||
void jswrap_ESP32_setLogLevel(JsVar *jsTagToSet, JsVar *jsLogLevel);
|
||||
void jswrap_ESP32_reboot();
|
||||
void jswrap_ESP32_setAtten(Pin pin,int atten);
|
||||
#endif /* TARGETS_ESP32_JSWRAP_ESP32_H_ */
|
||||
240
targets/esp32/jswrap_rtos.c
Normal file
240
targets/esp32/jswrap_rtos.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Task, queue and timer specific exposed components.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "jswrap_rtos.h"
|
||||
#include "jsparse.h"
|
||||
#include "rtosutil.h"
|
||||
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"class" : "Queue"
|
||||
}
|
||||
A class to support some simple Queue handling for RTOS queues
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "constructor",
|
||||
"class" : "Queue",
|
||||
"name" : "Queue",
|
||||
"generate" : "jswrap_Queue_constructor",
|
||||
"params" : [ ["queueName", "JsVar", "Name of the queue"] ],
|
||||
"return" : ["JsVar","A Queue object"]
|
||||
}
|
||||
Creates a Queue Object
|
||||
*/
|
||||
JsVar *jswrap_Queue_constructor(JsVar *queueName){
|
||||
int idx; char name[20];
|
||||
JsVar *queue = jspNewObject(0, "Queue");
|
||||
if (!queue) return 0;
|
||||
name[jsvGetString(queueName, name, sizeof(name))] = '\0';
|
||||
idx = queue_indexByName(name);
|
||||
jsvObjectSetChildAndUnLock(queue, "index", jsvNewFromInteger(idx));
|
||||
return queue;
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Queue",
|
||||
"name" : "read",
|
||||
"generate" : "jswrap_Queue_read"
|
||||
}
|
||||
reads one character from queue, if available
|
||||
*/
|
||||
void jswrap_Queue_read(JsVar *parent) {
|
||||
char data;
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
queue_read(jsvGetInteger(idx));
|
||||
jsvUnLock(idx);
|
||||
return;
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Queue",
|
||||
"name" : "writeChar",
|
||||
"params" : [ ["char", "JsVar", "char to be send"] ],
|
||||
"generate" : "jswrap_Queue_writeChar"
|
||||
}
|
||||
Writes one character to queue
|
||||
*/
|
||||
void jswrap_Queue_writeChar(JsVar *parent,char c){
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
queue_writeChar(idx,c);
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Queue",
|
||||
"name" : "log",
|
||||
"generate" : "jswrap_Queue_log"
|
||||
}
|
||||
logs list of queues
|
||||
*/
|
||||
void jswrap_Queue_log(JsVar *parent) {
|
||||
queue_list();
|
||||
return;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"class" : "Task"
|
||||
}
|
||||
A class to support some simple Task handling for RTOS tasks
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "constructor",
|
||||
"class" : "Task",
|
||||
"name" : "Task",
|
||||
"generate" : "jswrap_Task_constructor",
|
||||
"params" : [ ["taskName", "JsVar", "Name of the task"] ],
|
||||
"return" : ["JsVar","A Task object"]
|
||||
}
|
||||
Creates a Task Object
|
||||
*/
|
||||
JsVar *jswrap_Task_constructor(JsVar *taskName){
|
||||
int idx; char name[20];
|
||||
JsVar *task = jspNewObject(0, "Task");
|
||||
if (!task) return 0;
|
||||
name[jsvGetString(taskName, name, sizeof(name))] = '\0';
|
||||
idx = task_indexByName(name);
|
||||
jsvObjectSetChildAndUnLock(task, "index", jsvNewFromInteger(idx));
|
||||
return task;
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Task",
|
||||
"name" : "suspend",
|
||||
"generate" : "jswrap_Task_suspend"
|
||||
}
|
||||
Suspend task, be careful not to suspend Espruino task itself
|
||||
*/
|
||||
void jswrap_Task_suspend(JsVar *parent){
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
task_Suspend(jsvGetInteger(idx));
|
||||
return;
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Task",
|
||||
"name" : "resume",
|
||||
"generate" : "jswrap_Task_resume"
|
||||
}
|
||||
Resumes a suspended task
|
||||
*/
|
||||
void jswrap_Task_resume(JsVar *parent){
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
task_Resume(jsvGetInteger(idx));
|
||||
return;
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Task",
|
||||
"name" : "getCurrent",
|
||||
"generate" : "jswrap_Task_getCurrent",
|
||||
"return" : ["JsVar","Name of current task"]
|
||||
}
|
||||
returns name of actual task
|
||||
*/
|
||||
JsVar *jswrap_Task_getCurrent(JsVar *parent){
|
||||
return jsvNewFromString(task_getCurrentName());
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Task",
|
||||
"name" : "notify",
|
||||
"generate" : "jswrap_Task_notify"
|
||||
}
|
||||
Sends a binary notify to task
|
||||
*/
|
||||
void jswrap_Task_notify(JsVar *parent){
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
task_notify(jsvGetInteger(idx));
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Task",
|
||||
"name" : "log",
|
||||
"generate" : "jswrap_Task_log"
|
||||
}
|
||||
logs list of tasks
|
||||
*/
|
||||
void jswrap_Task_log(JsVar *parent) {
|
||||
task_list();
|
||||
return;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"class" : "Timer"
|
||||
}
|
||||
A class to handle Timer on base of ESP32 Timer
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "constructor",
|
||||
"class" : "Timer",
|
||||
"name" : "Timer",
|
||||
"generate" : "jswrap_Timer_constructor",
|
||||
"params" : [ ["timerName", "JsVar", "Timer Name"],
|
||||
["group", "int", "Timer group"],
|
||||
["index", "int", "Timer index"],
|
||||
["isrIndex", "int", "isr (0 = Espruino, 1 = test)"] ],
|
||||
"return" : ["JsVar","A Timer Object"]
|
||||
}
|
||||
Creates a Timer Object
|
||||
*/
|
||||
JsVar *jswrap_Timer_constructor(JsVar *timerName,int group, int index, int isrIndex){
|
||||
int idx; char name[20];
|
||||
JsVar *timer = jspNewObject(0, "Timer");
|
||||
if(!timer) return 0;
|
||||
name[jsvGetString(timerName, name, sizeof(name))] = '\0';
|
||||
idx = timer_Init(name,group,index,isrIndex);
|
||||
jsvObjectSetChildAndUnLock(timer, "index", jsvNewFromInteger(idx));
|
||||
return timer;
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Timer",
|
||||
"name" : "start",
|
||||
"params" : [["duration","int","duration of timmer in micro secs"]],
|
||||
"generate" : "jswrap_Timer_start"
|
||||
}
|
||||
Starts a timer
|
||||
*/
|
||||
void jswrap_Timer_start(JsVar *parent, int duration){
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
timer_Start(jsvGetInteger(idx),duration);
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Timer",
|
||||
"name" : "reschedule",
|
||||
"params" : [["duration","int","duration of timmer in micro secs"]],
|
||||
"generate" : "jswrap_Timer_reschedule"
|
||||
}
|
||||
Reschedules a timer, needs to be started at least once
|
||||
*/
|
||||
void jswrap_Timer_reschedule(JsVar *parent, int duration){
|
||||
JsVar *idx = jsvObjectGetChild(parent,"index",1);
|
||||
timer_Reschedule(jsvGetInteger(idx),duration);
|
||||
}
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Timer",
|
||||
"name" : "log",
|
||||
"generate" : "jswrap_Timer_log"
|
||||
}
|
||||
logs list of timers
|
||||
*/
|
||||
void jswrap_Timer_log(JsVar *parent) {
|
||||
timer_List();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
42
targets/esp32/jswrap_rtos.h
Normal file
42
targets/esp32/jswrap_rtos.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2015 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Task, queue and timer specific exposed components.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TARGETS_JSWRAP_RTOS_H_
|
||||
#define TARGETS_JSWRAP_RTOS_H_
|
||||
|
||||
#include "jsvar.h"
|
||||
|
||||
//===== Queue Library
|
||||
JsVar *jswrap_Queue_constructor(JsVar *queueName);
|
||||
void jswrap_Queue_read(JsVar *parent);
|
||||
void jswrap_Queue_writeChar(JsVar *parent,char c);
|
||||
void jswrap_Queue_log(JsVar *parent);
|
||||
|
||||
// ==== Task handling
|
||||
JsVar *jswrap_Task_constructor(JsVar *taskName);
|
||||
void jswrap_Task_suspend(JsVar *parent);
|
||||
void jswrap_Task_resume(JsVar *parent);
|
||||
JsVar *jswrap_Task_getCurrent(JsVar *parent);
|
||||
void jswrap_Task_notify(JsVar *taskName);
|
||||
void jswrap_Task_log(JsVar *parent);
|
||||
|
||||
// ==== Timer handling
|
||||
JsVar *jswrap_Timer_constructor(JsVar *timerName,int group, int index, int isrIndex);
|
||||
void jswrap_Timer_start(JsVar *parent, int duration);
|
||||
void jswrap_Timer_reschedule(JsVar *parent, int duration);
|
||||
void jswrap_Timer_log(JsVar *parent);
|
||||
|
||||
#endif /* TARGETS_JSWRAP_RTOS_H_ */
|
||||
81
targets/esp32/main.c
Normal file
81
targets/esp32/main.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <jsdevices.h>
|
||||
#include <jsinteractive.h>
|
||||
#include "rtosutil.h"
|
||||
#include "jstimer.h"
|
||||
#include "jshardwareUart.h"
|
||||
#include "jshardwareAnalog.h"
|
||||
#include "jshardwareTimer.h"
|
||||
#include "jshardwarePWM.h"
|
||||
#include "jshardwarePulse.h"
|
||||
#include "spi.h" //rename to jahardwareSPI.h ?
|
||||
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
extern void jswrap_ESP32_wifi_restore(void) ;
|
||||
|
||||
extern void initialise_wifi(void);
|
||||
|
||||
static void uartTask(void *data) {
|
||||
initConsole();
|
||||
while(1) {
|
||||
consoleToEspruino();
|
||||
serialToEspruino();
|
||||
}
|
||||
}
|
||||
|
||||
static void timerTask(void *data) {
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
timers_Init();
|
||||
timer_Init("EspruinoTimer",0,0,0);
|
||||
timer_List();
|
||||
while(1) {
|
||||
taskWaitNotify();
|
||||
jstUtilTimerInterruptHandler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void espruinoTask(void *data) {
|
||||
PWMInit();
|
||||
RMTInit();
|
||||
SPIChannelsInit();
|
||||
initADC(1);
|
||||
jshInit(); // Initialize the hardware
|
||||
jswrap_ESP32_wifi_restore();
|
||||
jsvInit(); // Initialize the variables
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
jsiInit(true); // Initialize the interactive subsystem
|
||||
while(1) {
|
||||
jsiLoop(); // Perform the primary loop processing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main entry point into Espruino on an ESP32.
|
||||
*/
|
||||
int app_main(void)
|
||||
{
|
||||
nvs_flash_init();
|
||||
spi_flash_init();
|
||||
tcpip_adapter_init();
|
||||
#ifdef RTOS
|
||||
queues_init();
|
||||
tasks_init();
|
||||
task_init(espruinoTask,"EspruinoTask",10000,5,0);
|
||||
task_init(uartTask,"ConsoleTask",2000,20,0);
|
||||
task_init(timerTask,"TimerTask",2048,19,0);
|
||||
#else
|
||||
xTaskCreatePinnedToCore(&espruinoTask, "espruinoTask", 10000, NULL, 5, NULL, 0);
|
||||
xTaskCreatePinnedToCore(&uartTask,"uartTask",2000,NULL,20,NULL,0);
|
||||
xTaskCreatePinnedToCore(&timerTask,"timerTask",2048,NULL,19,NULL,0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
249
targets/esp32/rtosutil.c
Normal file
249
targets/esp32/rtosutil.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* This file is designed to support FREERTOS functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Task, queue and timer specific exposed components.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rom/uart.h"
|
||||
#include "rtosutil.h"
|
||||
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "driver/timer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// implementation of simple queue oriented commands. see header file for more info.
|
||||
void queues_init(){
|
||||
int i;
|
||||
for(i = 0; i < queueMax; i++){ RTOSqueues[i].name = NULL; RTOSqueues[i].handle = NULL;}
|
||||
}
|
||||
int queue_indexByName(char *queueName){
|
||||
int i;
|
||||
for(i = 0; i < queueMax; i++){
|
||||
if(RTOSqueues[i].handle != 0){
|
||||
if(strcmp(queueName,RTOSqueues[i].name) == 0){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
QueueHandle_t queue_handleByName(char *queueName){
|
||||
int idx;
|
||||
idx = queue_indexByName(queueName);
|
||||
return RTOSqueues[idx].handle;
|
||||
}
|
||||
int queue_init(char *queueName,int length,int sizeOfEntry){
|
||||
int i;
|
||||
for(i = 0; i < queueMax; i++){
|
||||
if(NULL == RTOSqueues[i].handle){
|
||||
RTOSqueues[i].name = queueName;
|
||||
RTOSqueues[i].handle = xQueueCreate(length,sizeOfEntry);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void queue_list(){
|
||||
int i;
|
||||
for(i = 0; i < queueMax; i++){
|
||||
if(RTOSqueues[i].name == NULL) return;
|
||||
printf("queue %s : %d\n",RTOSqueues[i].name,RTOSqueues[i].handle);
|
||||
}
|
||||
}
|
||||
char *queue_read(int idx){
|
||||
char data;
|
||||
if(xQueueReceive(RTOSqueues[idx].handle,&data,0)){
|
||||
return data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void queue_writeChar(int idx,char c){
|
||||
if(!xQueueSend(RTOSqueues[idx].handle,&c,1)){
|
||||
printf("SerialTaskOverflow\n");
|
||||
}
|
||||
}
|
||||
|
||||
// implementation of simple task oriented commands. see header file for more info.
|
||||
void tasks_init(){
|
||||
int i;
|
||||
for(i = 0; i < taskMax; i++){ RTOStasks[i].name = NULL; RTOStasks[i].handle = NULL;}
|
||||
}
|
||||
int task_indexByName(char *taskName){
|
||||
int i;
|
||||
for(i = 0; i < taskMax; i++){
|
||||
if(RTOStasks[i].handle != 0){
|
||||
if(strcmp(taskName,RTOStasks[i].name) == 0){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
TaskHandle_t task_handleByName(char *taskName){
|
||||
int idx;
|
||||
idx = task_indexByName(taskName);
|
||||
return RTOStasks[idx].handle;
|
||||
}
|
||||
int *task_getCurrentIndex(){
|
||||
int i;TaskHandle_t handle;
|
||||
handle = xTaskGetCurrentTaskHandle();
|
||||
for(i = 0; i < taskMax; i++){
|
||||
if(RTOStasks[i].handle == handle){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
char *task_getCurrentName(){
|
||||
int i;TaskHandle_t handle;
|
||||
handle = xTaskGetCurrentTaskHandle();
|
||||
for(i = 0; i < taskMax; i++){
|
||||
if(RTOStasks[i].handle == handle){
|
||||
return RTOStasks[i].name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
int task_init(TaskFunction_t taskCode, char *taskName,unsigned short stackDepth,UBaseType_t priority,BaseType_t coreId){
|
||||
int i;
|
||||
for(i = 0; i < taskMax; i++){
|
||||
if(NULL == RTOStasks[i].handle){
|
||||
RTOStasks[i].name = taskName;
|
||||
xTaskCreatePinnedToCore(taskCode,taskName,stackDepth,NULL,priority,&RTOStasks[i].handle,coreId);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void task_list(){
|
||||
int i;
|
||||
for(i = 0; i < taskMax;i++){
|
||||
if(RTOStasks[i].name == NULL) return;
|
||||
printf("task %s : %d\n",RTOStasks[i].name,RTOStasks[i].handle);
|
||||
}
|
||||
}
|
||||
void task_Suspend(int idx){
|
||||
vTaskSuspend(RTOStasks[idx].handle);
|
||||
}
|
||||
void task_Resume(int idx){
|
||||
vTaskResume(RTOStasks[idx].handle);
|
||||
}
|
||||
void task_notify(int idx){
|
||||
xTaskNotifyGive(RTOStasks[idx].handle);
|
||||
}
|
||||
void taskWaitNotify(){
|
||||
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
|
||||
}
|
||||
|
||||
#define TIMER_INTR_SEL TIMER_INTR_LEVEL /*!< Timer level interrupt */
|
||||
#define TIMER_GROUP TIMER_GROUP_0 /*!< Test on timer group 0 */
|
||||
#define TIMER_DIVIDER 80 /*!< Hardware timer clock divider */
|
||||
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */
|
||||
#define TIMER_FINE_ADJ (1.4*(TIMER_BASE_CLK / TIMER_DIVIDER)/1000000) /*!< used to compensate alarm value */
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
void IRAM_ATTR espruino_isr(void *para){
|
||||
int idx = (int) para;
|
||||
//printf("y%d",idx);
|
||||
if(idx == 0){
|
||||
TIMERG0.hw_timer[TIMER_0].update = 1;
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
}
|
||||
else{
|
||||
TIMERG0.hw_timer[TIMER_1].update = 1;
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
}
|
||||
vTaskNotifyGiveFromISR(RTOStasks[ESP32Timers[idx].taskToNotifyIdx].handle,&xHigherPriorityTaskWoken);
|
||||
}
|
||||
void IRAM_ATTR test_isr(void *para){
|
||||
int idx = (int) para;
|
||||
printf("x\n");
|
||||
if(idx == 0){
|
||||
TIMERG0.hw_timer[TIMER_0].update = 1;
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
}
|
||||
else{
|
||||
TIMERG0.hw_timer[TIMER_1].update = 1;
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void timers_Init(){
|
||||
int i;
|
||||
for(i = 0; i < timerMax; i++){
|
||||
ESP32Timers[i].name = NULL;
|
||||
}
|
||||
}
|
||||
int timer_indexByName(char *timerName){
|
||||
int i;
|
||||
for(i = 0; i < timerMax; i++){
|
||||
if(ESP32Timers[i].name == NULL) return -1;
|
||||
if(strcmp(timerName,ESP32Timers[i].name) == 0){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int timer_Init(char *timerName,int group,int index,int isr_idx){
|
||||
int i;
|
||||
for(i = 0; i < timerMax; i++){
|
||||
if(ESP32Timers[i].name == NULL){
|
||||
ESP32Timers[i].name = timerName;
|
||||
ESP32Timers[i].group = group;
|
||||
ESP32Timers[i].index = index;
|
||||
timer_config_t config;
|
||||
config.alarm_en = 1;
|
||||
config.auto_reload = 1;
|
||||
config.counter_dir = TIMER_COUNT_UP;
|
||||
config.divider = TIMER_DIVIDER;
|
||||
config.intr_type = TIMER_INTR_SEL;
|
||||
config.counter_en = TIMER_PAUSE;
|
||||
timer_init(group, index, &config);/*Configure timer*/
|
||||
timer_pause(group, index);/*Stop timer counter*/
|
||||
timer_set_counter_value(group, index, 0x00000000ULL);/*Load counter value */
|
||||
timer_enable_intr(group, index);
|
||||
if(isr_idx == 0){
|
||||
ESP32Timers[i].taskToNotifyIdx = task_indexByName("TimerTask");
|
||||
timer_isr_register(group, index, espruino_isr, (void*) i, ESP_INTR_FLAG_IRAM, NULL);
|
||||
}
|
||||
else{
|
||||
timer_isr_register(group, index, test_isr, (void*) i, ESP_INTR_FLAG_IRAM, NULL);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void timer_Start(int idx,uint64_t duration){
|
||||
//printf("StartTimer:%d = %d\n",idx,duration);
|
||||
timer_enable_intr(ESP32Timers[idx].group, ESP32Timers[idx].index);
|
||||
timer_set_alarm_value(ESP32Timers[idx].group, ESP32Timers[idx].index, duration - TIMER_FINE_ADJ);
|
||||
TIMERG0.hw_timer[idx].config.alarm_en = 1;
|
||||
timer_start(ESP32Timers[idx].group, ESP32Timers[idx].index);
|
||||
}
|
||||
void timer_Reschedule(int idx,uint64_t duration){
|
||||
//printf("reschedule:%d\n",cnt++);
|
||||
timer_set_alarm_value(ESP32Timers[idx].group, ESP32Timers[idx].index, duration - TIMER_FINE_ADJ);
|
||||
TIMERG0.hw_timer[idx].config.alarm_en = 1;
|
||||
}
|
||||
void timer_List(){
|
||||
int i;
|
||||
for(i = 0; i < timerMax; i++){
|
||||
if(ESP32Timers[i].name == NULL){printf("timer %d free\n",i);}
|
||||
else {printf("timer %s : %d.%d\n",ESP32Timers[i].name,ESP32Timers[i].group,ESP32Timers[i].index);}
|
||||
}
|
||||
return;
|
||||
}
|
||||
63
targets/esp32/rtosutil.h
Normal file
63
targets/esp32/rtosutil.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is designed to support FREERTOS functions in Espruino,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Juergen Marsch
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Publici
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Task, queue and timer specific exposed components.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
|
||||
#define queueMax 10 //for queus we use an array of name/handle info. Core RTOS is not very helpful for this
|
||||
struct RTOSqueue{ char *name;QueueHandle_t handle;};
|
||||
struct RTOSqueue RTOSqueues[queueMax];
|
||||
|
||||
#define taskMax 10 //for tasks we use an array of name/handle info similiar to queue array
|
||||
struct RTOStask{ char *name;TaskHandle_t handle;int rx;};
|
||||
struct RTOStask RTOStasks[taskMax];
|
||||
|
||||
#define timerMax 2 //for Timer we use an array of timer relevant info
|
||||
struct ESP32Timer{ char *name; int group; int index; uint64_t duration; int taskToNotifyIdx; };
|
||||
struct ESP32Timer ESP32Timers[timerMax];
|
||||
|
||||
void queues_init(); //initializes array of queues
|
||||
int queue_indexByName(char *queueName); //returns index of queue in queue array by name
|
||||
QueueHandle_t queue_handleByName(char *queueName); //returns handle of queue by name
|
||||
int queue_init(char *queueName,int length,int sizeOfEntry); //initializes a queue with name,length and size of each entry
|
||||
char *queue_read(int idx); //reads one character from queue
|
||||
void queue_writeChar(int idx,char c); //writes one char to queue
|
||||
void queue_list(); //logs queue list
|
||||
|
||||
void tasks_init(); //initializes array of tasks
|
||||
int task_indexByName(char *taskName); //returns index of task in task array by name
|
||||
TaskHandle_t task_handleByName(char *taskName); //returns handle of task by name
|
||||
int *task_getCurrentIndex(); //returns index of actual task
|
||||
char *task_getCurrentName(); //returns name of actual task
|
||||
int task_init(TaskFunction_t taskCode, char *taskName,unsigned short stackDepth,UBaseType_t priority,BaseType_t coreId);
|
||||
//initializes a task, using nonstandard rtos api call xTaskCreatePinnedToCore
|
||||
void task_list(); //lists all entrys of task array usinf printf
|
||||
void task_Suspend(int idx); //suspends task given by index in task array
|
||||
void task_Resume(int idx); //resumes task given by index in task array
|
||||
void task_notify(int idx); //notify task given by index with binary
|
||||
void taskWaitNotify(); //waits for notify
|
||||
|
||||
void timers_Init();
|
||||
int timer_indexByName(char *timerName);
|
||||
int timer_Init(char *timerName,int group,int index,int isr_idx);
|
||||
void timer_Start(int idx,uint64_t duration);
|
||||
void timer_Reschedule(int idx,uint64_t duration);
|
||||
void timer_List();
|
||||
|
||||
void console_readToQueue(); //reads char from uart and writes to RTOS queue, not using interrupts (yet)
|
||||
203
targets/esp32/spi.c
Normal file
203
targets/esp32/spi.c
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* This file is designed to support spi functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Rhys Williams (wilberforce)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jspininfo.h"
|
||||
#include "jshardware.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "spi.h"
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
int getSPIChannelPnt(IOEventFlags device){
|
||||
return device - EV_SPI1;
|
||||
}
|
||||
void SPIChannelsInit(){
|
||||
int i;
|
||||
for(i = 0; i < SPIMax; i++){
|
||||
SPIChannels[i].spi = NULL;
|
||||
SPIChannels[i].spi_read = false;
|
||||
SPIChannels[i].g_lastSPIRead = (uint32_t)-1;
|
||||
}
|
||||
SPIChannels[0].HOST = HSPI_HOST;
|
||||
SPIChannels[1].HOST = VSPI_HOST;
|
||||
}
|
||||
|
||||
void jshSetDeviceInitialised(IOEventFlags device, bool isInit);
|
||||
|
||||
/*
|
||||
https://hackadaycom.files.wordpress.com/2016/10/esp32_pinmap.png
|
||||
HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
|
||||
15 HSPI SS
|
||||
14 HSPI SCK
|
||||
12 HSPI MISO
|
||||
13 HSPI MOSI
|
||||
VSPI 3 //SPI bus normally attached to pin:
|
||||
5 VSPI SS
|
||||
18 VSPI SCK
|
||||
19 VSPI MISO
|
||||
23 VSPI MOSI
|
||||
|
||||
Does not correspond to:
|
||||
https://github.com/espressif/esp-idf/blob/master/examples/26_spi_master/main/spi_master.c#L34
|
||||
|
||||
#define PIN_NUM_MISO 25
|
||||
#define PIN_NUM_MOSI 23
|
||||
#define PIN_NUM_CLK 19
|
||||
#define PIN_NUM_CS 22
|
||||
|
||||
#define PIN_NUM_DC 21
|
||||
#define PIN_NUM_RST 18
|
||||
#define PIN_NUM_BCKL 5
|
||||
|
||||
To do:
|
||||
implement inf->spiMSB
|
||||
Test with ILI9341 works, but could be faster.
|
||||
Espruino supports sendig byte by byte, no mass sending is supported.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize the hardware SPI device.
|
||||
* On the ESP32, hardware SPI is implemented via a set of default pins defined
|
||||
* as follows:
|
||||
*
|
||||
*
|
||||
*/
|
||||
void jshSPISetup(
|
||||
IOEventFlags device, //!< The identity of the SPI device being initialized.
|
||||
JshSPIInfo *inf //!< Flags for the SPI device.
|
||||
) {
|
||||
|
||||
int channelPnt = getSPIChannelPnt(device);
|
||||
Pin sck, miso, mosi;
|
||||
if(SPIChannels[channelPnt].HOST == HSPI_HOST){
|
||||
sck = inf->pinSCK != PIN_UNDEFINED ? inf->pinSCK : 14;
|
||||
miso = inf->pinMISO != PIN_UNDEFINED ? inf->pinMISO : 12;
|
||||
mosi = inf->pinMOSI != PIN_UNDEFINED ? inf->pinMOSI : 13;
|
||||
}
|
||||
else {
|
||||
sck = inf->pinSCK != PIN_UNDEFINED ? inf->pinSCK : 5;
|
||||
miso = inf->pinMISO != PIN_UNDEFINED ? inf->pinMISO : 19;
|
||||
mosi = inf->pinMOSI != PIN_UNDEFINED ? inf->pinMOSI : 23;
|
||||
}
|
||||
|
||||
spi_bus_config_t buscfg={
|
||||
.miso_io_num=miso,
|
||||
.mosi_io_num=mosi,
|
||||
.sclk_io_num=sck,
|
||||
.quadwp_io_num=-1,
|
||||
.quadhd_io_num=-1
|
||||
};
|
||||
// SPI_DEVICE_BIT_LSBFIRST - test inf->spiMSB need to look at what values...
|
||||
uint32_t flags = 0;
|
||||
|
||||
spi_device_interface_config_t devcfg={
|
||||
.clock_speed_hz=inf->baudRate,
|
||||
.mode=inf->spiMode,
|
||||
.spics_io_num= -1, //set CS not used by driver
|
||||
.queue_size=7, //We want to be able to queue 7 transactions at a time
|
||||
.flags=flags
|
||||
};
|
||||
if(SPIChannels[channelPnt].spi){
|
||||
spi_bus_remove_device(SPIChannels[channelPnt].spi);
|
||||
spi_bus_free(SPIChannels[channelPnt].HOST);
|
||||
jsWarn("spi was already in use, removed old assignment");
|
||||
}
|
||||
esp_err_t ret=spi_bus_initialize(SPIChannels[channelPnt].HOST, &buscfg, 1);
|
||||
assert(ret==ESP_OK);
|
||||
ret = spi_bus_add_device(SPIChannels[channelPnt].HOST, &devcfg, &SPIChannels[channelPnt].spi);
|
||||
assert(ret==ESP_OK);
|
||||
|
||||
jshSetDeviceInitialised(device, true);
|
||||
}
|
||||
|
||||
/** Send data through the given SPI device (if data>=0), and return the result
|
||||
* of the previous send (or -1). If data<0, no data is sent and the function
|
||||
* waits for data to be returned */
|
||||
int jshSPISend(
|
||||
IOEventFlags device, //!< The identity of the SPI device through which data is being sent.
|
||||
int data //!< The data to be sent or an indication that no data is to be sent.
|
||||
) {
|
||||
int channelPnt = getSPIChannelPnt(device);
|
||||
uint8_t byte = (uint8_t)data;
|
||||
//os_printf("> jshSPISend - device=%d, data=%x\n", device, data);
|
||||
int retData = (int)SPIChannels[channelPnt].g_lastSPIRead;
|
||||
if (data >=0) {
|
||||
// Send 8 bits of data taken from "data" over the selected spi and store the returned
|
||||
// data for subsequent retrieval.
|
||||
//spiTransferBits(_spi[which_spi], (uint32_t)data, &g_lastSPIRead, 8);
|
||||
esp_err_t ret;
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(t)); //Zero out the transaction
|
||||
t.length=8; //Command is 8 bits
|
||||
t.tx_buffer=&data; //The data is the cmd itself
|
||||
// https://esp-idf.readthedocs.io/en/latest/api/spi_master.html#type-definitions
|
||||
// should this be a switch or always read?
|
||||
t.flags=SPI_TRANS_USE_RXDATA;
|
||||
ret=spi_device_transmit(SPIChannels[channelPnt].spi, &t); //Transmit - blocks until result - need to change this?
|
||||
assert(ret == ESP_OK);
|
||||
SPIChannels[channelPnt].g_lastSPIRead=t.rx_data[0];
|
||||
|
||||
} else {
|
||||
SPIChannels[channelPnt].g_lastSPIRead = (uint32_t)-1;
|
||||
}
|
||||
return (int)retData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send 16 bit data through the given SPI device.
|
||||
*/
|
||||
void jshSPISend16(
|
||||
IOEventFlags device, //!< Unknown
|
||||
int data //!< Unknown
|
||||
) {
|
||||
int channelPnt = getSPIChannelPnt(device);
|
||||
//spiWriteWord(_spi[which_spi], data);
|
||||
jsError(">> jshSPISend16: Not implemented");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to send 16 bits or 8 over SPI.
|
||||
*/
|
||||
void jshSPISet16(
|
||||
IOEventFlags device, //!< Unknown
|
||||
bool is16 //!< Unknown
|
||||
) {
|
||||
UNUSED(device);
|
||||
UNUSED(is16);
|
||||
jsError(">> jshSPISend16: Not implemented");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wait until SPI send is finished.
|
||||
*/
|
||||
void jshSPIWait(
|
||||
IOEventFlags device //!< Unknown
|
||||
) {
|
||||
int channelPnt = getSPIChannelPnt(device);
|
||||
//spiWaitReady(_spi[which_spi]);
|
||||
//jsError(">> jshSPIWait: Not implemented");
|
||||
}
|
||||
|
||||
|
||||
/** Set whether to use the receive interrupt or not */
|
||||
void jshSPISetReceive(IOEventFlags device, bool isReceive) {
|
||||
int channelPnt = getSPIChannelPnt(device);
|
||||
SPIChannels[channelPnt].spi_read = isReceive;
|
||||
}
|
||||
42
targets/esp32/spi.h
Normal file
42
targets/esp32/spi.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is designed to support spi functions in Espruino for ESP32,
|
||||
* a JavaScript interpreter for Microcontrollers designed by Gordon Williams
|
||||
*
|
||||
* Copyright (C) 2016 by Rhys Williams (wilberforce)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains ESP32 board specific functions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jspininfo.h"
|
||||
#include "jshardware.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
// Convert an Espruino pin to an ESP32 pin number.
|
||||
gpio_num_t pinToESP32Pin(Pin pin);
|
||||
|
||||
#define SPIMax 2
|
||||
struct SPIChannel{
|
||||
spi_device_handle_t spi;
|
||||
bool spi_read;
|
||||
uint32_t g_lastSPIRead;
|
||||
spi_host_device_t HOST;
|
||||
};
|
||||
struct SPIChannel SPIChannels[SPIMax];
|
||||
void SPIChannelsInit();
|
||||
|
||||
void jshSPISetup( IOEventFlags device, JshSPIInfo *inf );
|
||||
|
||||
int jshSPISend( IOEventFlags device, int data );
|
||||
void jshSPISend16( IOEventFlags device, int data );
|
||||
void jshSPISet16( IOEventFlags device, bool is16 );
|
||||
void jshSPIWait( IOEventFlags device );
|
||||
void jshSPISetReceive(IOEventFlags device, bool isReceive);
|
||||
46
targets/esp32/tests/buttons-led.js
Normal file
46
targets/esp32/tests/buttons-led.js
Normal file
@ -0,0 +1,46 @@
|
||||
console.log('Button and GPIO tests');
|
||||
// Led on D22 should flash once per second
|
||||
// [boot] button on board should toggle led state
|
||||
// Any one wire devices on D23 should be listed.
|
||||
var led = Pin(D23);
|
||||
var led = Pin(D22);
|
||||
//var led = Pin(D15); //
|
||||
//
|
||||
|
||||
var toggle=1;
|
||||
|
||||
|
||||
//pinMode(F5, "input");
|
||||
digitalWrite(D23, 0);
|
||||
pinMode(D23, "input");
|
||||
var ow = new OneWire(D23);
|
||||
|
||||
|
||||
console.log('look for one wire');
|
||||
var sensors = ow.search().map(function (device) {
|
||||
console.log(device);
|
||||
return require("DS18B20").connect(ow, device);
|
||||
});
|
||||
|
||||
console.log(sensors);
|
||||
|
||||
|
||||
function updateLed(){
|
||||
digitalWrite(led, toggle);
|
||||
toggle=!toggle;
|
||||
}
|
||||
|
||||
// Boot button 1 up 0 down
|
||||
digitalRead(D0);
|
||||
|
||||
function button_down() {
|
||||
updateLed();
|
||||
print('button');
|
||||
}
|
||||
|
||||
setWatch(button_down,D0, {repeat:true, edge:"rising"});
|
||||
|
||||
setInterval( function() {
|
||||
//console.log('tick');
|
||||
updateLed();
|
||||
}, 1000 );
|
||||
15
targets/esp32/tests/get_web_page.js
Normal file
15
targets/esp32/tests/get_web_page.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Connect to an access point and get a web page.
|
||||
//
|
||||
var ssid="guest";
|
||||
var password="kolbanguest";
|
||||
|
||||
var wifi=require("Wifi");
|
||||
wifi.connect(ssid, {password: password}, function() {
|
||||
console.log("Connected to access point, getting web page");
|
||||
var http = require("http");
|
||||
http.get("http://www.espruino.com", function(res) {
|
||||
res.on('data', function(data) {
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
15
targets/esp32/tests/get_web_page_https.js
Normal file
15
targets/esp32/tests/get_web_page_https.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Connect to an access point and get a web page.
|
||||
//
|
||||
var ssid="guest";
|
||||
var password="kolbanguest";
|
||||
|
||||
var wifi=require("Wifi");
|
||||
wifi.connect(ssid, {password: password}, function() {
|
||||
console.log("Connected to access point, getting web page");
|
||||
var http = require("http");
|
||||
http.get("https://httpbin.org/ip", function(res) {
|
||||
res.on('data', function(data) {
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
43
targets/esp32/tests/https-google-sheets.js
Normal file
43
targets/esp32/tests/https-google-sheets.js
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
|
||||
var okey = atob("MIIEogIBAAKCAQEAwcBeteXIax0S+gNFv4f0K+q4LOv/E7kmiT8IvZl85NvUDF/slro/x/EreRMGmjcxoeT7+U62nrVu07lZhc+WAiluBX6Ykb2h7lJ/1M3MKV4uK5Yq92p1MxVXzYhVbCKBmcKrPu7Od+hLIMLIMTu0zwc23cE4tSUP4WV38BAzol3k9Rhd1MIjdZ3QUBTYYrvPveUv1TCdsQNsAGv5ZhJx57Anm52W7jTzwBw1O4cn31TD0KD3US/yDKL2IH7BSBFiadN5AzBJbh/ch16/aOfUBIlKNZf9LofMOVLxNm9hxpP2vgckl9u9nTtWiCR5EmKZaTqTqN7bsoLkNKR1GJ6yBwIBIwKCAQAQm3XVE7IXz0rE+PdZj09xeoTQpoOT+e1cOJpZZO1ys8G36vcFmu+GKp1ThUm1cnH37w5Ikbfht8erv24SyKZ1NsBJnSMFLYLoirp/9GH06tDB6EzTYOV5aDq52HxZudCYJqD2xAMRl5FpNURb/c2rWGPJ3Vyhz/oMAWINQzegM8in120G0ZmEnbdvdDWivWKJ4Ap1/fqiWr6yBLbG7gKnLkU3PksQG0YtTahSGXdfEPAi7+CIcRi8svM2Agecm7DH3MW/pgHY8JX87psAmgqCONyVqcAiBlBwQrIk59pczKuzCOSp66STM5S7pXwIuWz/YDJPaGPIL8U/GAyQvJxjAoGBAPfc71FJNg+pKvQMUybGutDtACkexYBNVInpkAKBtGszPjN8xVmmh9huHj+zooFSxQPB2FmsNW7i69pf09FFFgf2tDL22BcG9VldpJR8l77EVw2arovoKC1TyCWxNvD+LYA6VIdd0OXUfUIXG9RGnnnNmHplO5IQ4ka2KI3XEuBtAoGBAMgcrRSRVBTBQtWEyz/cCivdrzdV2AaoNtv5+k0o2pJrViHvrCbhGZNBc/R0u4s3dM53L2IX0w065LD1PeyKjaFXZO2lx3Iu3lf4L8U6oEVQ8C8eLQUOwJ8dK1fWp304Z/iwStwmTa0TZE05KKhl+31NlSOlNr2CHfWeY1So81vDAoGBAKn2lXmRSaRWvl40VkZ5pKyFQfBPnV9K+CQN3xepZcXZ/sQ4TM/CpktEMf/LoqHSWzXGwD19ZnfsD3ErxHI+AHp9SF12EITRkkvocNrZF5jBJcAvjaHDw8dPZKwhv0YqotuVtk4xs9DMOKJY/SPYpy7zYT38RhsEQ2OwG8754Q7rAoGASlPLQidZvpDs8DijQ5rfNN1PtXeoAnj+bvZy6XWTAy8unuP+HRHHq7k5spHCAIJP9Opwr2fvTg6PdO1gJKh9v5V9QlOEmCAJcSGrV+KTTPItU1RZ3U6fUQrVlaeACfBhIdsUfafTtVBYdHRQ7hdAJzoS0rm1PxMScSwzhdhaY+kCgYEAtpWlQzz7u+lurGKbKZY1cTPiFprA9PIsCtl0A5PdQ1XPnYfBgVAlB26oF9ubNy8VxpoerT7VlfILOSBRHx4n2VaUe/7iyZX4yNC+J8zKyLLq8ea0GC76d/masFMuWvZcuOk0afnBZ4VffGUxYMdjP8CEWFJjYjJpsWzW3uWB2ek=");
|
||||
|
||||
var ocert = atob("MIIFijCCA3KgAwIBAgIJAJhrfxuduldTMA0GCSqGSIb3DQEBCwUAMIGBMQswCQYDVQQGEwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcTBkJvc3RvbjETMBEGA1UEChMKRXhhbXBsZSBDbzEQMA4GA1UECxMHdGVjaG9wczELMAkGA1UEAxMCY2ExIDAeBgkqhkiG9w0BCQEWEWNlcnRzQGV4YW1wbGUuY29tMB4XDTE1MTEyNzEyMjM1NloXDTE4MDgyMjEyMjM1NlowgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNQTEPMA0GA1UEBxMGQm9zdG9uMRMwEQYDVQQKEwpFeGFtcGxlIENvMRAwDgYDVQQLEwd0ZWNob3BzMRAwDgYDVQQDEwdjbGllbnQxMSAwHgYJKoZIhvcNAQkBFhFjZXJ0c0BleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANEmBWwVwLrRcIzF2Juu45tfP0CO88/80QlBMZPPAT7HbIo1YLeBGy3d12LxywT8/1zGlsxxA5xJS1wumUE3xIOAZRZG++6JshstfNPvUNbmIFNNvr3cKpppWX7rPqK39/cKniBaoLLl6RaYrIuBDcgL1Pofs5XbdsPk92fn82KyDrpyYzuI6KNjWMTtyoIDiC8vftY9JeL+IMAVQ3s+oNdxQiE1sU252BSDVXymGxoKDs8+EpbCnTkU8HdffZ4o7rWFEj9FzM/PgZmNF9c2YLsLLlh3QmMxZhfXdMmElgfCbK54uKsujFFxQI+whX2gwy1qeWkJBywSpj7g4SDizIN8jXetT5J4r/zSURKwlMeboZdUd5fs1us4JtN0Ba2D7Tch+cKenyM/iRo3HPVXvsL2FA4cuEdEwOM8kADeZqIO9yrfp3rNsKkEY/a8e96jLniRx1DD9Csk8xvXk95UBTAuSZeg3oGFPBALa6XK3PKLd1EHm4un9DO2TvgaypfSIudz0hXqapOavxz2IyOyqigpJqDR9fXe9WKa3oD0fwS5SgBmcjmy/73JTDDiv4fgCztLPZgSftMPNBy3HDJxyf1uRVyOOMebL4jfxVrgM/kIzMSz4YSMGazKLknKz9x6PtEmjEeVlJNAmoXmT6zXA9N+4+kUanG6XE2IrvD+MfnrAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAAPv3w4KVca2vZeaPN4kHb7ln1ZkXimZ/jZYJMdFh0xcwnTgGQiW+P2voIJuA1GsrrdLvD27RnV1UKtDbJT+MZB5nM/mt7BMyQKdHEGy1YFFLFQz4YMaUEoif5OXFFnmunEu76C90qwbxBpUiS3lB97Gipy3VDBJKFE2kYaypYJc0XqIJcnypzsLBU/K9Bl13Xvj7QNN2VyqDGKlw6v6UJWRyYT7efqvvJ5Ljglmdn1UxX+WmfLzKtO+aMBoSuOgyFEttLLKESYXYRRcomfCRxqIH3XA3PzyDEN5R/wG38IQD3Y0Zt+UYabS6qUKtD2jMD8dL1gr7NWLraDSPAre2fBbHtjskr8vyR5PjrBFLJWOzEQKzclxW3O6cmZKyjwd092JuNn+FSjgo/glWik8jyFXJzK5bLXgGFa31YFnrmWKDrxbAWCuJL6UcRx4rX9qdPkZpwPTqN1sEh1YqdZShxDTFjbxDrE8gL5xbo62q9bdzbN/TMzhVo1BYvQytt7MbX2ZEXDXOup2QiOs23MqcQsf3yjT25OD5V9w3NWXDcd+TLsNCdKFnY+EpWOe4qs7k4UuXJMcW/zAPPBZDPEBsi+AAYsNYEo8QdsCcNtiWD818fTjHR6nmNRsMjRH9jeM9x0N/fJvsuCrrMQZF5KNpntOP0lV1ktAIcjQJUf93rN+");
|
||||
|
||||
var oca = atob("MIIFgDCCA2gCCQD1KANs3obrTjANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMQ8wDQYDVQQHEwZCb3N0b24xEzARBgNVBAoTCkV4YW1wbGUgQ28xEDAOBgNVBAsTB3RlY2hvcHMxCzAJBgNVBAMTAmNhMSAwHgYJKoZIhvcNAQkBFhFjZXJ0c0BleGFtcGxlLmNvbTAeFw0xNTExMjcxMjIyMzFaFw00MzA0MTMxMjIyMzFaMIGBMQswCQYDVQQGEwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcTBkJvc3RvbjETMBEGA1UEChMKRXhhbXBsZSBDbzEQMA4GA1UECxMHdGVjaG9wczELMAkGA1UEAxMCY2ExIDAeBgkqhkiG9w0BCQEWEWNlcnRzQGV4YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwjlJ3eyrnGIiJiplY5mvIaaoMC20oR4Jx5+FOXNJJhjSz9mOoqcpEe2U6ZmmVfcpc8zdt1f9KkED5yjzpnF02CG+KYaRs/Rfj0NJejcpBN3Hn4R6+yJek2rYrKi4uZyMZrWx/8PTp/lEypAEBf/2vX9WYNgi5eWyHeHEfJ4yucRI1UgRw5W/RLYoAePAPT1ekB66NbosBIZhRXJvjqED/jOMOlpHgNPQHTUyPj5lR8ZTSduATUQac6qRx9pdYyVICVE8bxma56R0pX8Cdx/wg+5gKOXUPuXW1xTPNuH4JpNTd7huJwa8Ff0ReKTLHZk1hYB7uDzL5moc8kylYEwz2W13KyXxZbh3kClVSNZvPbrcp1eWoyJyznLRLVv3cCWQwmEMr1071Th4/6dnUZ/wl085HIjV93X9H8nzZ7VBkwHD8ZHB1foW0/jgbK0qsH2gV7frGFPxZydmk/Nrwdl3RtoM+xEpQI7cPYDf9j/CX/ynM4LfOeHhVfMrx0I3E8wNPX9MU+O+Pu6wsT4WbGkNhcuS4oE2As13obMnUebLwOxxWu4ErI8WG1ITwRVEQik72Iqj0d5vvjZw2z5TFzkMB/Tl3qNvAp9jzpNtvRUyrS6KRY667BZOJ9TJK/5+jenGEi7+UNq9ig490WnYDBPA/N9QSPHCx6TLNapayQvem5UCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAS9mpX4QgnwntvH9wutY+zOWBLejd/psjjVmZdYzeVC6fkCaw0Qj1unszq58EHlA8275ARTYyicRHIYLF3ZDYwMxUCu7iIQJUzVYJRqowV2Ap4OeMlh5sUb/Wlmhs5TauSZ1gz4LqMqnGkVMrvvU+1WX2ePFl81nnr1UMb2+dLzC0Gj2jH3tlzW76yFD4gElR8W4ypgvAw9pFKlSuOc4y6KS32jaOJk9zWSigPQadI1pOSSk+iKuPp98BBY/gDw+FBKUNARo3ci5F2s1dJZwQSCnuBhVb1r+3aHjnp4PAO7Mq7YyFf7qwSmuA++nF7TGhu3lf3hY1Jzgo+rOi+pFZtebCsewLDJjyNUxhQkOIf4TutC9wPJUtCKDpLA0iJso1AX5297iap5g7y0J0fUls16U+F0arsBHhgIN5ARifImeE+1bVVx7kLtklA23njczUt88ylgsCEnYyu0U+0+kwAkMDyPWDd3KPfDhykhQJ0Ev/44+JTDk3zydO2YvCpqMqLuhbZr9mvmV7uzJVbFnLr3sU75upv0N4JQLIn3XyTtDbWjTqA8d6qbG5BxYL5xkrWRxo3Fd6r1AyFje1ilKUkwZ1YZZCDvgv/2uEFyL0VlgfHfBhNbN2nsTTxijKc19ROeIRXl7eqWq/cyIbA/5LzEy2UbbEhKIroPGosQML4sc=");
|
||||
|
||||
|
||||
// Actually send a form
|
||||
function sendForm() {
|
||||
// This uploads to https://docs.google.com/spreadsheets/d/1R1D6GKK5MvtjS-PDEPHdqIqKSYX4kG4dPHkj_lkL1P0/pubhtml
|
||||
//LED1.set(); // light red LED while we're working
|
||||
var content = "entry.1093163892="+encodeURIComponent(E.getTemperature());
|
||||
var options = {
|
||||
host: 'docs.google.com',
|
||||
port: '443',
|
||||
path:'/forms/d/1bBV4map47MPRWfaHYCEd1ByR4f_sm3LSd3oRdYkiVKg/formResponse',
|
||||
protocol: "https:",
|
||||
method:'POST',
|
||||
headers: {
|
||||
"Content-Type":"application/x-www-form-urlencoded",
|
||||
"Content-Length":content.length
|
||||
},
|
||||
key : okey,
|
||||
ca : oca,
|
||||
cert : ocert
|
||||
};
|
||||
|
||||
console.log("Connecting to Google");
|
||||
require("http").request(options, function(res) {
|
||||
console.log("Connected to Google");
|
||||
var nRecv = 0;
|
||||
res.on('data', function(data) { nRecv += data.length; });
|
||||
res.on('close', function(data) {
|
||||
//LED1.reset(); // turn red LED off when finished
|
||||
console.log("Google connection closed, "+nRecv+" bytes received");
|
||||
});
|
||||
}).end(content);
|
||||
}
|
||||
|
||||
sendForm();
|
||||
|
||||
26
targets/esp32/tests/i2c-hd44780.js
Normal file
26
targets/esp32/tests/i2c-hd44780.js
Normal file
@ -0,0 +1,26 @@
|
||||
I2C1.setup({"scl":D17,"sda":D16,bitrate:100000});
|
||||
var lcd = require("HD44780").connectI2C(I2C1);
|
||||
lcd.print("Hello ESP32!!");
|
||||
|
||||
/*
|
||||
function isDevice(i2cBus,id) {
|
||||
try {
|
||||
return i2cBus.readFrom(id,1);
|
||||
}
|
||||
catch(err) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
function detect(i2c,first,last) {
|
||||
first = first | 0;
|
||||
last = last | 0x77;
|
||||
var idsOnBus = Array();
|
||||
for (var id = first; id < last; id++) {
|
||||
if ( isDeviceOnBus(i2c,id) != -1)
|
||||
idsOnBus.push(id);
|
||||
}
|
||||
}
|
||||
return idsOnBus;
|
||||
}
|
||||
console.log(detect(I2C1));
|
||||
*/
|
||||
18
targets/esp32/tests/mqttclient.js
Normal file
18
targets/esp32/tests/mqttclient.js
Normal file
@ -0,0 +1,18 @@
|
||||
var ssid="RASPI3";
|
||||
var password="password";
|
||||
|
||||
var wifi=require("Wifi");
|
||||
wifi.connect(ssid, {password: password}, function() {
|
||||
console.log("Connected to access point");
|
||||
var mqtt = require("MQTT").create("192.168.5.1");
|
||||
mqtt.on("connected", function() {
|
||||
console.log("MQTT connected");
|
||||
mqtt.subscribe("test");
|
||||
mqtt.on('publish', function (pub) {
|
||||
console.log("topic: "+pub.topic);
|
||||
console.log("message: "+pub.message);
|
||||
});
|
||||
});
|
||||
console.log("Doing a connect");
|
||||
mqtt.connect();
|
||||
});
|
||||
6
targets/esp32/tests/network_scan.js
Normal file
6
targets/esp32/tests/network_scan.js
Normal file
@ -0,0 +1,6 @@
|
||||
var wifi=require("Wifi");
|
||||
wifi.scan(function(data) {
|
||||
for (var i=0; i<data.length; i++) {
|
||||
console.log(JSON.stringify(data[i]));
|
||||
}
|
||||
});
|
||||
7
targets/esp32/tests/one-wire.js
Normal file
7
targets/esp32/tests/one-wire.js
Normal file
@ -0,0 +1,7 @@
|
||||
pinMode(D4,'input');
|
||||
var ow = new OneWire(D4);
|
||||
|
||||
var sensors = ow.search().map(function (device) {
|
||||
return require("DS18B20").connect(ow, device);
|
||||
});
|
||||
console.log(sensors);
|
||||
28
targets/esp32/tests/rainbow-led.js
Normal file
28
targets/esp32/tests/rainbow-led.js
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
var toggle = true;
|
||||
|
||||
function updateLed() {
|
||||
digitalWrite(led, toggle);
|
||||
toggle=!toggle;
|
||||
}
|
||||
function button_down() {
|
||||
updateLed();
|
||||
print('button');
|
||||
}
|
||||
var red = D18;
|
||||
var green = D19;
|
||||
var blue = D22;
|
||||
var led = blue;
|
||||
|
||||
digitalWrite(red, 0);
|
||||
digitalWrite(green, 0);
|
||||
digitalWrite(blue, 0);
|
||||
|
||||
|
||||
setInterval(function () {updateLed();}, 1000);
|
||||
setWatch(button_down, "D0", { repeat:true, edge:'rising' });
|
||||
|
||||
digitalWrite(red, 0);
|
||||
digitalWrite(green, 0);
|
||||
digitalWrite(blue, 0);
|
||||
|
||||
66
targets/esp32/tests/select_accesspoint.js
Normal file
66
targets/esp32/tests/select_accesspoint.js
Normal file
@ -0,0 +1,66 @@
|
||||
// Start being an access point.
|
||||
// Start being a web server.
|
||||
// Listen on:
|
||||
// - /list - Return a list of access points
|
||||
// - /select?ssid=<SSID>&password=<password> - Select an SSID and supply a password.
|
||||
// When a request arrives from a browser, build a page which contains the
|
||||
// list of access points to which we can connect.
|
||||
// When the user selects an access point with password, connect to that access point.
|
||||
|
||||
|
||||
// 2. Configure a Web Server.
|
||||
function startWebServer() {
|
||||
var http = require("http");
|
||||
var httpServer = http.createServer(function(request, response) {
|
||||
console.log("Received a browser request looking for " + request.url);
|
||||
// Handle browser requests here ...
|
||||
var parsedURL = url.parse(request.url, true);
|
||||
if (parsedURL.pathname == "/list") {
|
||||
// Process the list request here ...
|
||||
// Handle the list request
|
||||
response.writeHead(200);
|
||||
response.end("process /list");
|
||||
return;
|
||||
} else if (parsedURL.pathname == "/select") {
|
||||
// Handle the select request
|
||||
if (!parsedURL.query.hasOwnProperty("ssid") || !parsedURL.query.hasOwnProperty("password")) {
|
||||
console.log("No ssid or no password in /select request: " + JSON.stringify(parsedURL));
|
||||
response.writeHead(200);
|
||||
response.end("Hello World");
|
||||
return;
|
||||
}
|
||||
// Process the select request here...
|
||||
response.writeHead(200);
|
||||
response.end("Process /select");
|
||||
return;
|
||||
}
|
||||
// Unknown service
|
||||
response.writeHead(200);
|
||||
response.end("Hello World");
|
||||
});
|
||||
httpServer.listen(80);
|
||||
console.log("Web Server now started ... listening on port 80");
|
||||
}
|
||||
var wifi = require("Wifi");
|
||||
|
||||
// 1. Be an access point
|
||||
|
||||
wifi.startAP("MYESP32", {
|
||||
"authMode": "open"
|
||||
}, function(err) {
|
||||
console.log("AP now started: " + err);
|
||||
startWebServer();
|
||||
});
|
||||
|
||||
|
||||
|
||||
//Connect to an access point and be a simple web server
|
||||
//
|
||||
/*
|
||||
var ssid="guest";
|
||||
var password="kolbanpassword";
|
||||
|
||||
wifi.connect(ssid, {password: password}, function() {
|
||||
startWebServer();
|
||||
});
|
||||
*/
|
||||
14
targets/esp32/tests/simple_web_server.js
Normal file
14
targets/esp32/tests/simple_web_server.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Connect to an access point and be a simple web server
|
||||
//
|
||||
var ssid="guest";
|
||||
var password="kolbanguest";
|
||||
|
||||
var wifi=require("Wifi");
|
||||
wifi.connect(ssid, {password: password}, function() {
|
||||
console.log("Connected to access point, listening for clients on port 8080.");
|
||||
var http = require("http");
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200);
|
||||
res.end("Hello World");
|
||||
}).listen(8080);
|
||||
});
|
||||
70
targets/esp32/tests/spi-nokia.js
Normal file
70
targets/esp32/tests/spi-nokia.js
Normal file
@ -0,0 +1,70 @@
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
IO4
|
||||
IO16
|
||||
IO17
|
||||
IO5
|
||||
IO18
|
||||
IO19
|
||||
|
||||
Display NodeMCU ESP-32 DEF Colour
|
||||
LED 3V3 3V3 N/A
|
||||
SCLCK D5 GPIO4 Green IO05
|
||||
DN<MOSI> D7 GPIO16 Yellow
|
||||
D/C D2 GPIO17 Orange
|
||||
SCE D8 GPIO5 Red
|
||||
RST D1 GPIO18 Brown
|
||||
GND GND GND Grey
|
||||
VCC 3V3 3V3 Blue
|
||||
BackLight GND GND Purple
|
||||
|
||||
|
||||
IO23 MOSI
|
||||
IO022
|
||||
TX0
|
||||
RX0
|
||||
IO21
|
||||
GND
|
||||
IO19 MISO
|
||||
IO18 SCK
|
||||
IO05 CS0
|
||||
IO17
|
||||
IO16
|
||||
IO04
|
||||
IO00
|
||||
IO02
|
||||
|
||||
|
||||
RST GPIO16 Brown
|
||||
CE GPIO5 Red
|
||||
DC GPIO17 Orange
|
||||
DIN GPIO23 Yellow
|
||||
CLK GPIO18 Green
|
||||
VCC VSS Blue
|
||||
LIGHT GND Purple
|
||||
GND GND Grey
|
||||
*/
|
||||
/*
|
||||
pinMode(D4, "input_pullup");
|
||||
pinMode(D16, "input_pullup");
|
||||
digitalWrite(D17, 0);
|
||||
digitalWrite(D18, 0);
|
||||
digitalWrite(D5, 0);
|
||||
*/
|
||||
|
||||
SPI2.setup({ sck:D5, mosi:D23 });
|
||||
|
||||
|
||||
var g = require("PCD8544").connect(SPI1,
|
||||
D17 /* RS / DC */,
|
||||
D18 /* CS / CE */,
|
||||
D16 /*RST*/, function() {
|
||||
g.clear();
|
||||
g.setRotation(2); //Flip display 180
|
||||
g.drawString("Hi Esp32",0,0);
|
||||
g.drawLine(0,10,84,10);
|
||||
g.flip();
|
||||
});
|
||||
3
targets/esp32/tests/timer1.js
Normal file
3
targets/esp32/tests/timer1.js
Normal file
@ -0,0 +1,3 @@
|
||||
setInterval(function() {
|
||||
console.log("tick");
|
||||
}, 1000);
|
||||
32
targets/esp32/tests/wifiEvents.js
Normal file
32
targets/esp32/tests/wifiEvents.js
Normal file
@ -0,0 +1,32 @@
|
||||
// Test ESP32 WiFi event callbacks
|
||||
var ssid="RASPI3";
|
||||
var password="password";
|
||||
|
||||
var wifi=require("Wifi");
|
||||
wifi.on("associated", function(details) {
|
||||
console.log("Event-> associated: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("connected", function(details) {
|
||||
console.log("Event-> connected: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("disconnected", function(details) {
|
||||
console.log("Event-> disconnected: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("auth_change", function(details) {
|
||||
console.log("Event-> auth_change: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("dhcp_timeout", function(details) {
|
||||
console.log("Event-> dhcp_timeout: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("probe_recv", function(details) {
|
||||
console.log("Event-> probe_recv: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("sta_joined", function(details) {
|
||||
console.log("Event-> sta_joined: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.on("sta_left", function(details) {
|
||||
console.log("Event-> sta_left: " + JSON.stringify(details));
|
||||
});
|
||||
wifi.connect(ssid, {password: password}, function() {
|
||||
console.log("Connect completed");
|
||||
});
|
||||
@ -15,6 +15,9 @@ esptool.py --port [/dev/ttyUSB0|COM1] --baud 115200 write_flash \
|
||||
|
||||
For 1MB flash use 0xFC000/0xFE000 and for 2MB flash use 0x1FC000/0x1FE000 on the last line.
|
||||
|
||||
*** Erase flash before updating to a new version
|
||||
esptool.py --port [/dev/ttyUSB0|COM1] --baud 115200 erase_flash
|
||||
|
||||
*** Get esptool.py from https://github.com/themadinventor/esptool
|
||||
|
||||
*** To flash a 4MB esp8266 (e.g. esp-12) via wifi use (with appropriate hostname):
|
||||
|
||||
@ -1329,3 +1329,99 @@ unsigned int jshSetSystemClock(JsVar *options) {
|
||||
*/
|
||||
void _exit(int status) {
|
||||
}
|
||||
|
||||
static inline uint32_t _getCycleCount(void) {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
bool jshNeopixelWrite(Pin pin, unsigned char *rgbData, size_t rgbSize) {
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Pin is not valid.");
|
||||
return false;
|
||||
}
|
||||
if (!jshGetPinStateIsManual(pin))
|
||||
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
|
||||
|
||||
// values for 160Mhz clock
|
||||
uint8_t tOne = 90; // one bit, high typ 800ns
|
||||
uint8_t tZero = 40; // zero bit, high typ 300ns
|
||||
uint8_t tLow = 170; // total cycle, typ 1.2us
|
||||
if (system_get_cpu_freq() < 100) {
|
||||
tOne = 56; // 56 cyc = 700ns
|
||||
tZero = 14; // 14 cycl = 175ns
|
||||
tLow = 100;
|
||||
}
|
||||
#define _BV(bit) (1 << (bit))
|
||||
|
||||
#if 1
|
||||
|
||||
// the loop over the RGB pixel bits below is loaded into the instruction cache from flash
|
||||
// with the result that dependeing on the cache line alignment the first loop iteration
|
||||
// takes too long and thereby messes up the first LED.
|
||||
// The fix is to make it so the first loop iteration does nothing, i.e. just outputs the
|
||||
// same "low" for the full loop as we had before entering this function. This way no LED
|
||||
// gets set to the wrong value and we load the cache line so the second iteration, i.e.,
|
||||
// first real LED bit, runs at full speed.
|
||||
uint32_t pinMask = _BV(pin); // bit mask for GPIO pin to write to reg
|
||||
uint8_t *p = (uint8_t *)rgbData; // pointer to walk through pixel array
|
||||
uint8_t *end = p + rgbSize; // pointer to end of array
|
||||
uint8_t pix = *p++; // current byte being shifted out
|
||||
uint8_t mask = 0x80; // mask for current bit
|
||||
uint32_t start; // start time of bit
|
||||
// adjust things for the pre-roll
|
||||
p--; // next byte we fetch will be the first byte again
|
||||
mask = 0x01; // fetch the next byte at the end of the first loop iteration
|
||||
pinMask = 0; // zero mask means we set or clear no I/O pin
|
||||
// iterate through all bits
|
||||
ets_intr_lock(); // disable most interrupts
|
||||
while(1) {
|
||||
uint32_t t;
|
||||
if (pix & mask) t = tOne;
|
||||
else t = tZero;
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
start = _getCycleCount(); // get start time of this bit
|
||||
while (_getCycleCount()-start < t) ; // busy-wait
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
if (!(mask >>= 1)) { // Next bit/byte?
|
||||
if (p >= end) break; // at end, we're done
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
pinMask = _BV(pin);
|
||||
}
|
||||
while (_getCycleCount()-start < tLow) ; // busy-wait
|
||||
}
|
||||
while (_getCycleCount()-start < tLow) ; // wait for last bit
|
||||
ets_intr_unlock();
|
||||
|
||||
#else
|
||||
|
||||
// this is the code without preloading the first bit
|
||||
uint32_t pinMask = _BV(pin); // bit mask for GPIO pin to write to reg
|
||||
uint8_t *p = (uint8_t *)rgbData; // pointer to walk through pixel array
|
||||
uint8_t *end = p + rgbSize; // pointer to end of array
|
||||
uint8_t pix = *p++; // current byte being shifted out
|
||||
uint8_t mask = 0x80; // mask for current bit
|
||||
uint32_t start; // start time of bit
|
||||
// iterate through all bits
|
||||
while(1) {
|
||||
uint32_t t;
|
||||
if (pix & mask) t = 56; // one bit, high typ 800ns (56 cyc = 700ns)
|
||||
else t = 14; // zero bit, high typ 300ns (14 cycl = 175ns)
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
start = _getCycleCount(); // get start time of this bit
|
||||
while (_getCycleCount()-start < t) ; // busy-wait
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
if (!(mask >>= 1)) { // Next bit/byte?
|
||||
if (p >= end) break; // at end, we're done
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
}
|
||||
while (_getCycleCount()-start < 100) ; // busy-wait, 100 cyc = 1.25us
|
||||
}
|
||||
while (_getCycleCount()-start < 100) ; // Wait for last bit
|
||||
|
||||
#endif
|
||||
#undef _BV
|
||||
}
|
||||
|
||||
@ -32,16 +32,8 @@ typedef long long int64_t;
|
||||
#include <network_esp8266.h>
|
||||
#include "jsinteractive.h" // Pull in the jsiConsolePrint function
|
||||
#include <log.h>
|
||||
#include <jswrap_espruino.h>
|
||||
|
||||
#define _BV(bit) (1 << (bit))
|
||||
|
||||
static uint32_t _getCycleCount(void) __attribute__((always_inline));
|
||||
|
||||
static inline uint32_t _getCycleCount(void) {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
// ESP8266.reboot
|
||||
|
||||
@ -318,110 +310,7 @@ JsVar *jswrap_ESP8266_crc32(JsVar *jsData) {
|
||||
]
|
||||
}*/
|
||||
void jswrap_ESP8266_neopixelWrite(Pin pin, JsVar *jsArrayOfData) {
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Pin is not valid.");
|
||||
return;
|
||||
}
|
||||
if (jsArrayOfData == NULL) {
|
||||
jsExceptionHere(JSET_ERROR, "No data to send to LEDs.");
|
||||
return;
|
||||
}
|
||||
|
||||
JSV_GET_AS_CHAR_ARRAY(pixels, dataLength, jsArrayOfData);
|
||||
if (!pixels) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataLength == 0) {
|
||||
jsExceptionHere(JSET_ERROR, "Data must be a non empty array.");
|
||||
return;
|
||||
}
|
||||
if (dataLength % 3 != 0) {
|
||||
jsExceptionHere(JSET_ERROR, "Data length must be a multiple of 3 (RGB).");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jshGetPinStateIsManual(pin))
|
||||
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
|
||||
|
||||
// values for 160Mhz clock
|
||||
uint8_t tOne = 90; // one bit, high typ 800ns
|
||||
uint8_t tZero = 40; // zero bit, high typ 300ns
|
||||
uint8_t tLow = 170; // total cycle, typ 1.2us
|
||||
if (system_get_cpu_freq() < 100) {
|
||||
tOne = 56; // 56 cyc = 700ns
|
||||
tZero = 14; // 14 cycl = 175ns
|
||||
tLow = 100;
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
||||
// the loop over the RGB pixel bits below is loaded into the instruction cache from flash
|
||||
// with the result that dependeing on the cache line alignment the first loop iteration
|
||||
// takes too long and thereby messes up the first LED.
|
||||
// The fix is to make it so the first loop iteration does nothing, i.e. just outputs the
|
||||
// same "low" for the full loop as we had before entering this function. This way no LED
|
||||
// gets set to the wrong value and we load the cache line so the second iteration, i.e.,
|
||||
// first real LED bit, runs at full speed.
|
||||
uint32_t pinMask = _BV(pin); // bit mask for GPIO pin to write to reg
|
||||
uint8_t *p = (uint8_t *)pixels; // pointer to walk through pixel array
|
||||
uint8_t *end = p + dataLength; // pointer to end of array
|
||||
uint8_t pix = *p++; // current byte being shifted out
|
||||
uint8_t mask = 0x80; // mask for current bit
|
||||
uint32_t start; // start time of bit
|
||||
// adjust things for the pre-roll
|
||||
p--; // next byte we fetch will be the first byte again
|
||||
mask = 0x01; // fetch the next byte at the end of the first loop iteration
|
||||
pinMask = 0; // zero mask means we set or clear no I/O pin
|
||||
// iterate through all bits
|
||||
ets_intr_lock(); // disable most interrupts
|
||||
while(1) {
|
||||
uint32_t t;
|
||||
if (pix & mask) t = tOne;
|
||||
else t = tZero;
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
start = _getCycleCount(); // get start time of this bit
|
||||
while (_getCycleCount()-start < t) ; // busy-wait
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
if (!(mask >>= 1)) { // Next bit/byte?
|
||||
if (p >= end) break; // at end, we're done
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
pinMask = _BV(pin);
|
||||
}
|
||||
while (_getCycleCount()-start < tLow) ; // busy-wait
|
||||
}
|
||||
while (_getCycleCount()-start < tLow) ; // wait for last bit
|
||||
ets_intr_unlock();
|
||||
|
||||
#else
|
||||
|
||||
// this is the code without preloading the first bit
|
||||
uint32_t pinMask = _BV(pin); // bit mask for GPIO pin to write to reg
|
||||
uint8_t *p = (uint8_t *)pixels; // pointer to walk through pixel array
|
||||
uint8_t *end = p + dataLength; // pointer to end of array
|
||||
uint8_t pix = *p++; // current byte being shifted out
|
||||
uint8_t mask = 0x80; // mask for current bit
|
||||
uint32_t start; // start time of bit
|
||||
// iterate through all bits
|
||||
while(1) {
|
||||
uint32_t t;
|
||||
if (pix & mask) t = 56; // one bit, high typ 800ns (56 cyc = 700ns)
|
||||
else t = 14; // zero bit, high typ 300ns (14 cycl = 175ns)
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
start = _getCycleCount(); // get start time of this bit
|
||||
while (_getCycleCount()-start < t) ; // busy-wait
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
if (!(mask >>= 1)) { // Next bit/byte?
|
||||
if (p >= end) break; // at end, we're done
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
}
|
||||
while (_getCycleCount()-start < 100) ; // busy-wait, 100 cyc = 1.25us
|
||||
}
|
||||
while (_getCycleCount()-start < 100) ; // Wait for last bit
|
||||
|
||||
#endif
|
||||
jswrap_E_neopixelWrite(pin, jsArrayOfData);
|
||||
}
|
||||
|
||||
//===== ESP8266.deepSleep
|
||||
|
||||
@ -811,3 +811,8 @@ void jshFlashWrite(void *buf, uint32_t addr, uint32_t len) { }
|
||||
unsigned int jshSetSystemClock(JsVar *options) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool jshNeopixelWrite(Pin pin, unsigned char *rgbData, size_t rgbSize) {
|
||||
jsExceptionHere(JSET_ERROR, "Neopixel writing not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -295,6 +295,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL) {
|
||||
m_central_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
bleSetActiveBluetoothGattServer(bleTaskInfo);
|
||||
jsvObjectSetChildAndUnLock(bleTaskInfo, "connected", jsvNewFromBool(true));
|
||||
bleCompleteTaskSuccess(BLETASK_CONNECT, bleTaskInfo);
|
||||
}
|
||||
@ -304,7 +305,18 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
if (m_central_conn_handle == p_ble_evt->evt.gap_evt.conn_handle) {
|
||||
JsVar *gattServer = bleGetActiveBluetoothGattServer();
|
||||
if (gattServer) {
|
||||
JsVar *bluetoothDevice = jsvObjectGetChild(gattServer, "device", 0);
|
||||
jsvObjectSetChildAndUnLock(gattServer, "connected", jsvNewFromBool(false));
|
||||
if (bluetoothDevice) {
|
||||
jsiQueueObjectCallbacks(bluetoothDevice, JS_EVENT_PREFIX"gattserverdisconnected", 0, 0);
|
||||
jshHadEvent();
|
||||
}
|
||||
jsvUnLock2(gattServer, bluetoothDevice);
|
||||
}
|
||||
m_central_conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
bleSetActiveBluetoothGattServer(0);
|
||||
BleTask task = bleGetCurrentTask();
|
||||
if (BLETASK_IS_CENTRAL(task)) {
|
||||
bleCompleteTaskFailAndUnLock(task, jsvNewFromString("Disconnected."));
|
||||
@ -411,13 +423,21 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
|
||||
case BLE_EVT_TX_COMPLETE:
|
||||
// BLE transmit finished - reset flags
|
||||
//TODO: probably want to figure out *which one* finished?
|
||||
bleStatus &= ~BLE_IS_SENDING;
|
||||
if (bleStatus & BLE_IS_SENDING_HID) {
|
||||
bleStatus &= ~BLE_IS_SENDING_HID;
|
||||
jsiQueueObjectCallbacks(execInfo.root, BLE_HID_SENT_EVENT, 0, 0);
|
||||
jsvObjectSetChild(execInfo.root, BLE_HID_SENT_EVENT, 0); // fire only once
|
||||
jshHadEvent();
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
if (p_ble_evt->evt.common_evt.conn_handle == m_central_conn_handle) {
|
||||
if (bleInTask(BLETASK_CHARACTERISTIC_WRITE))
|
||||
bleCompleteTaskSuccess(BLETASK_CHARACTERISTIC_WRITE, 0);
|
||||
}
|
||||
#endif
|
||||
if (p_ble_evt->evt.common_evt.conn_handle == m_conn_handle) {
|
||||
//TODO: probably want to figure out *which one* finished?
|
||||
bleStatus &= ~BLE_IS_SENDING;
|
||||
if (bleStatus & BLE_IS_SENDING_HID) {
|
||||
bleStatus &= ~BLE_IS_SENDING_HID;
|
||||
jsiQueueObjectCallbacks(execInfo.root, BLE_HID_SENT_EVENT, 0, 0);
|
||||
jsvObjectSetChild(execInfo.root, BLE_HID_SENT_EVENT, 0); // fire only once
|
||||
jshHadEvent();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -529,6 +549,17 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
jsvObjectSetChildAndUnLock(o,"uuid", bleUUIDToStr(p_chr->uuid));
|
||||
jsvObjectSetChildAndUnLock(o,"handle_value", jsvNewFromInteger(p_chr->handle_value));
|
||||
jsvObjectSetChildAndUnLock(o,"handle_decl", jsvNewFromInteger(p_chr->handle_decl));
|
||||
JsVar *p = jsvNewObject();
|
||||
if (p) {
|
||||
jsvObjectSetChildAndUnLock(p,"broadcast",jsvNewFromBool(p_chr->char_props.broadcast));
|
||||
jsvObjectSetChildAndUnLock(p,"read",jsvNewFromBool(p_chr->char_props.read));
|
||||
jsvObjectSetChildAndUnLock(p,"writeWithoutResponse",jsvNewFromBool(p_chr->char_props.write_wo_resp));
|
||||
jsvObjectSetChildAndUnLock(p,"write",jsvNewFromBool(p_chr->char_props.write));
|
||||
jsvObjectSetChildAndUnLock(p,"notify",jsvNewFromBool(p_chr->char_props.notify));
|
||||
jsvObjectSetChildAndUnLock(p,"indicate",jsvNewFromBool(p_chr->char_props.indicate));
|
||||
jsvObjectSetChildAndUnLock(p,"authenticatedSignedWrites",jsvNewFromBool(p_chr->char_props.auth_signed_wr));
|
||||
jsvObjectSetChildAndUnLock(o,"properties", p);
|
||||
}
|
||||
// char_props?
|
||||
jsvArrayPushAndUnLock(bleTaskInfo, o);
|
||||
}
|
||||
@ -562,9 +593,34 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP:
|
||||
jsiConsolePrintf("DESC\n");
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP: if (bleInTask(BLETASK_CHARACTERISTIC_DESC_AND_STARTNOTIFY)) {
|
||||
// trigger this with sd_ble_gattc_descriptors_discover(conn_handle, &handle_range);
|
||||
uint16_t cccd_handle = 0;
|
||||
ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt = &p_ble_evt->evt.gattc_evt.params.desc_disc_rsp;
|
||||
if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_SUCCESS) {
|
||||
// The descriptor was found at the peer.
|
||||
// If the descriptor was a CCCD, then the cccd_handle needs to be populated.
|
||||
uint32_t i;
|
||||
// Loop through all the descriptors to find the CCCD.
|
||||
for (i = 0; i < p_desc_disc_rsp_evt->count; i++) {
|
||||
if (p_desc_disc_rsp_evt->descs[i].uuid.uuid ==
|
||||
BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) {
|
||||
cccd_handle = p_desc_disc_rsp_evt->descs[i].handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cccd_handle) {
|
||||
if(bleTaskInfo)
|
||||
jsvObjectSetChildAndUnLock(bleTaskInfo, "handle_cccd", jsvNewFromInteger(cccd_handle));
|
||||
|
||||
// FIXME: we just switch task here - this is not nice...
|
||||
bleSwitchTask(BLETASK_CHARACTERISTIC_NOTIFY);
|
||||
jsble_central_characteristicNotify(bleTaskInfo, true);
|
||||
} else {
|
||||
bleCompleteTaskFailAndUnLock(BLETASK_CHARACTERISTIC_DESC_AND_STARTNOTIFY, jsvNewFromString("CCCD Handle not found"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP: if (bleInTask(BLETASK_CHARACTERISTIC_READ)) {
|
||||
ble_gattc_evt_read_rsp_t *p_read = &p_ble_evt->evt.gattc_evt.params.read_rsp;
|
||||
@ -590,11 +646,17 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
if (handles) {
|
||||
JsVar *characteristic = jsvGetArrayItem(handles, p_hvx->handle);
|
||||
if (characteristic) {
|
||||
// TODO: should return {target:characteristic} and set characteristic.value
|
||||
JsVar *data = jsvNewStringOfLength(p_hvx->len);
|
||||
if (data) jsvSetString(data, (const char*)p_hvx->data, p_hvx->len);
|
||||
jsiQueueObjectCallbacks(characteristic, "characteristicvaluechanged", &data, 1);
|
||||
jshHadEvent();
|
||||
// Set characteristic.value, and return {target:characteristic}
|
||||
jsvObjectSetChildAndUnLock(characteristic, "value",
|
||||
jsvNewTypedArrayWithData(ARRAYBUFFERVIEW_UINT8, p_hvx->len, (unsigned char*)p_hvx->data));
|
||||
|
||||
JsVar *evt = jsvNewObject();
|
||||
if (evt) {
|
||||
jsvObjectSetChild(evt, "target", characteristic);
|
||||
jsiQueueObjectCallbacks(characteristic, JS_EVENT_PREFIX"characteristicvaluechanged", &evt, 1);
|
||||
jshHadEvent();
|
||||
jsvUnLock(evt);
|
||||
}
|
||||
}
|
||||
jsvUnLock2(characteristic, handles);
|
||||
}
|
||||
@ -1108,6 +1170,11 @@ void jsble_restart_softdevice() {
|
||||
if (advData || advOpt) jswrap_nrf_bluetooth_setAdvertising(advData, advOpt);
|
||||
jsvUnLock2(advData, advOpt);
|
||||
|
||||
// If we had scan response data set, update it
|
||||
JsVar *scanData = jsvObjectGetChild(execInfo.hiddenRoot, BLE_NAME_SCAN_RESPONSE_DATA, 0);
|
||||
if (scanData) jswrap_nrf_bluetooth_setScanResponse(scanData);
|
||||
jsvUnLock(scanData);
|
||||
|
||||
// if we were scanning, make sure we restart
|
||||
if (bleStatus & BLE_IS_SCANNING) {
|
||||
JsVar *callback = jsvObjectGetChild(execInfo.root, BLE_SCAN_EVENT, 0);
|
||||
@ -1347,23 +1414,22 @@ void jsble_nfc_start(const uint8_t *data, size_t len) {
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
void jsble_central_connect(ble_gap_addr_t peer_addr) {
|
||||
uint32_t err_code;
|
||||
// TODO: do these really need to be static?
|
||||
|
||||
static ble_gap_scan_params_t m_scan_param;
|
||||
ble_gap_scan_params_t m_scan_param;
|
||||
memset(&m_scan_param, 0, sizeof(m_scan_param));
|
||||
m_scan_param.active = 1; // Active scanning set.
|
||||
m_scan_param.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); // Scan interval.
|
||||
m_scan_param.window = MSEC_TO_UNITS(50, UNIT_0_625_MS); // Scan window.
|
||||
m_scan_param.window = MSEC_TO_UNITS(90, UNIT_0_625_MS); // Scan window.
|
||||
m_scan_param.timeout = 4; // 4 second timeout.
|
||||
|
||||
static ble_gap_conn_params_t gap_conn_params;
|
||||
ble_gap_conn_params_t gap_conn_params;
|
||||
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
|
||||
gap_conn_params.min_conn_interval = MSEC_TO_UNITS(7.5, UNIT_1_25_MS);
|
||||
gap_conn_params.max_conn_interval = MSEC_TO_UNITS(1000, UNIT_1_25_MS);
|
||||
gap_conn_params.max_conn_interval = MSEC_TO_UNITS(500, UNIT_1_25_MS);
|
||||
gap_conn_params.slave_latency = 0;
|
||||
gap_conn_params.conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS);
|
||||
|
||||
static ble_gap_addr_t addr;
|
||||
ble_gap_addr_t addr;
|
||||
addr = peer_addr;
|
||||
|
||||
err_code = sd_ble_gap_connect(&addr, &m_scan_param, &gap_conn_params);
|
||||
@ -1407,9 +1473,20 @@ void jsble_central_characteristicWrite(JsVar *characteristic, char *dataPtr, siz
|
||||
return bleCompleteTaskFailAndUnLock(BLETASK_CHARACTERISTIC_WRITE, jsvNewFromString("Not connected"));
|
||||
|
||||
uint16_t handle = jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_value", 0));
|
||||
bool writeWithoutResponse = false;
|
||||
JsVar *properties = jsvObjectGetChild(characteristic, "properties", 0);
|
||||
if (properties) {
|
||||
writeWithoutResponse = jsvGetBoolAndUnLock(jsvObjectGetChild(properties, "writeWithoutResponse", 0));
|
||||
jsvUnLock(properties);
|
||||
}
|
||||
|
||||
|
||||
ble_gattc_write_params_t write_params;
|
||||
memset(&write_params, 0, sizeof(write_params));
|
||||
write_params.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
if (writeWithoutResponse)
|
||||
write_params.write_op = BLE_GATT_OP_WRITE_CMD; // write without response
|
||||
else
|
||||
write_params.write_op = BLE_GATT_OP_WRITE_REQ; // write with response
|
||||
// BLE_GATT_OP_WRITE_REQ ===> BLE_GATTC_EVT_WRITE_RSP (write with response)
|
||||
// or BLE_GATT_OP_WRITE_CMD ===> BLE_EVT_TX_COMPLETE (simple write)
|
||||
// or send multiple BLE_GATT_OP_PREP_WRITE_REQ,...,BLE_GATT_OP_EXEC_WRITE_REQ (with offset + 18 bytes in each for 'long' write)
|
||||
@ -1436,12 +1513,31 @@ void jsble_central_characteristicRead(JsVar *characteristic) {
|
||||
bleCompleteTaskFail(BLETASK_CHARACTERISTIC_READ, 0);
|
||||
}
|
||||
|
||||
void jsble_central_characteristicDescDiscover(JsVar *characteristic) {
|
||||
if (!jsble_has_central_connection())
|
||||
return bleCompleteTaskFailAndUnLock(BLETASK_CHARACTERISTIC_DESC_AND_STARTNOTIFY, jsvNewFromString("Not connected"));
|
||||
|
||||
// start discovery for our single handle only
|
||||
uint16_t handle_value = (uint16_t)jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_value", 0));
|
||||
|
||||
ble_gattc_handle_range_t range;
|
||||
range.start_handle = handle_value+1;
|
||||
range.end_handle = handle_value+1;
|
||||
|
||||
uint32_t err_code;
|
||||
err_code = sd_ble_gattc_descriptors_discover(m_central_conn_handle, &range);
|
||||
if (jsble_check_error(err_code)) {
|
||||
bleCompleteTaskFail(BLETASK_CHARACTERISTIC_DESC_AND_STARTNOTIFY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void jsble_central_characteristicNotify(JsVar *characteristic, bool enable) {
|
||||
if (!jsble_has_central_connection())
|
||||
return bleCompleteTaskFailAndUnLock(BLETASK_CHARACTERISTIC_NOTIFY, jsvNewFromString("Not connected"));
|
||||
|
||||
uint16_t cccd_handle = jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_cccd", 0));
|
||||
// FIXME: we need the cccd handle to be populated for this to work
|
||||
if (!cccd_handle)
|
||||
return bleCompleteTaskFailAndUnLock(BLETASK_CHARACTERISTIC_NOTIFY, jsvNewFromString("handle_cccd not set"));
|
||||
|
||||
uint8_t buf[BLE_CCCD_VALUE_LEN];
|
||||
buf[0] = enable ? BLE_GATT_HVX_NOTIFICATION : 0;
|
||||
|
||||
@ -60,6 +60,7 @@ extern uint16_t bleAdvertisingInterval; /**< The advertising interval
|
||||
extern uint16_t m_conn_handle; /**< Handle of the current connection. */
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
extern uint16_t m_central_conn_handle; /**< Handle for central mode connection */
|
||||
|
||||
#endif
|
||||
|
||||
/** Initialise the BLE stack */
|
||||
@ -124,6 +125,8 @@ void jsble_central_getCharacteristics(JsVar *service, ble_uuid_t uuid);
|
||||
void jsble_central_characteristicWrite(JsVar *characteristic, char *dataPtr, size_t dataLen);
|
||||
// Read data from the given characteristic. When done call bleCompleteTask
|
||||
void jsble_central_characteristicRead(JsVar *characteristic);
|
||||
// Discover descriptors of characteristic
|
||||
void jsble_central_characteristicDescDiscover(JsVar *characteristic);
|
||||
// Set whether to notify on the given characteristic. When done call bleCompleteTask
|
||||
void jsble_central_characteristicNotify(JsVar *characteristic, bool enable);
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user