Compare commits

..

1 Commits

Author SHA1 Message Date
sago35 592f66e1ca rtl8720dn: add Rpc_tcpip_adapter_init_with_timeout() 2022-08-01 17:37:15 +09:00
324 changed files with 3649 additions and 11752 deletions
+2 -5
View File
@@ -11,13 +11,10 @@ on:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/tinygo-org/tinygo-dev
container: tinygo/tinygo-dev
steps:
- name: Work around CVE-2022-24765
# We're not on a multi-user machine, so this is safe.
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: TinyGo version check
run: tinygo version
- name: Enforce Go Formatted Code
-221
View File
@@ -1,224 +1,3 @@
0.25.0
---
- **core**
- add Sensor interface and Measurement type
- **delay**
- add new package for cycle-accurate delays
- **new devices**
- **AS560x**
- Add support for ams AS560x on-axis magnetic rotary position sensors
- **onewire**
- first implementation of 1-wire protocol (#505)
- **mpu6886**
- initial implementation
- **ttp229**
- initial support for ttp229 (BSF)
- **enhancements**
- **gps**
- make the date available in addition to the time (#532)
- **i2csoft**
- use cycle counting for delays
- **ili9341**
- add EnableTEOutput to be able to sync drawing with VSYNC
- add sleep mode
- unify rotation support
- **st7735**
- add DrawRGBBitmap8 method to draw raw RGB565 buffers
- add sleep mode
- unify rotation support
- **st7789**
- added DrawRGBBitmap8 (same as ili9341 & st7735)
- allow changing the color format using COLMOD
- make it possible to configure gamma
- support the chip select pin
- update saved rotation in SetRotation
- add sleep mode
- unify rotation support
- **sx126x/sx127x**
- Reduce spi buffer size, add missing select when using channels
- Remove heap alloc in interrupt, add non blocking channel send/receive, and other cleanups
- **wifinina**
- add generated strings, improved debugging system and messages
- add ResetIsHigh to control the behavior of the RESET pin for boards like the Arduino MKR 1010
- only add generated strings when using wifidebug tag
- **bugfixes**
- **ds3231**
- Document incorrect leap year 2100
- Fix negative temperature conversion
- **ili9341**
- fix Size() for mirrored rotation
- **st7789**
- avoid heap allocations after the driver is created
- **net**
- Revert "(#501) make IP.String() method return something sensible"
- **wifinina**
- small timing adjustments in Configure() to better ensure device reset
- **examples**
- **sdcard**
- remove tinyfs example and replace with link to tinyfs repo in docs
- **wifinina**
- improve connectToAP() and other needed minor corrections
- **build**
- switch to ghcr.io for docker container
- run smoke tests in parallel
- **Makefile**
- add XTENSA=0 flag to skip Xtensa tests
- remove AVR=0 flag
- **docs**
- remove full list of devices from README, better to keep it on the tinygo.org site
- update LICENSE year
0.24.0
---
- **new devices**
- **lora**
- created shared RadioEvent
- move shared config for sx126x/sx127x to single package
- **lorawan**
- add initial LoRaWAN stack support
- Basic implementation of Lorawan Regional Settings and EU868/AU915 regions
- **qmi8658c**
- Add support for the QMI8658C sensor (#467)
- **sh1106**
- add support for SH1106 display driver
- **sx127x**
- Driver for Semtech sx127x radio modules
- **enhancements**
- **bme280**
- improve config support
- add ReadAltitude() function copied from BMP280 driver
- **buzzer**
- make all note durations float64
- no tone during rest
- **dht22**
- update DHT22 receive to use runtime/interrupt
- **gps**
- add support for GLL sentence type, add original sentence to gps errors
- improve error handling
- improve parsing and add tests to verify
- **microbitmatrix**
- add link to schema for microbit V2
- add smoke test for microbitmatrix with microbit-v2
- add support for brightness of led pixels
- harmonize v1 and v2 implementation
- move Size() to version agnostic part
- **mpu6050**
- add functions to configure clock, and scaling for accelerometer and gyroscope
- **net/http**
- add PostForm()
- **sx126x**
- add Reset() and needed pin
- move RadioController into separate file for clarity
- pre-define all errors to avoid heap allocations
- refactor to RadioController interface to more easily handle non-STM32WL boards and remove duplicated code
- **vl53l1x**
- Add getter for the effective SPAD count
- **wifinina**
- add support for http server (#480)
- **bugfixes**
- **lsm303agr**
- fix I2C address auto increment for multi data read
- **net**
- (#501) make IP.String() method return something sensible
- **mpu6050**
- return I2C error when configuring fails
- **sx126x**
- fix in SetBandwidth function
- actually set the frequency when calling SetFrequency()
- correct RX/TX pin mapping for TheThingsIndustries GNSE board
- **examples**
- **LoRaWAN**
- example with LoRaWAN AT command set implementation
- basic example
- update all remaining examples for refactored API
- **sx126x**
- fix bandwidth,tx power in lora//lora_continuous example
- **sx127x**
- rx/tx example
- **build**
- remove older format build tags
- update to actions/checkout@v3
- work around for CVE-2022-24765
0.23.0
---
- **new devices**
- Add GC9A01 Driver (#452)
- Initial support for VL6180x sensor
- **enhancements**
- **rtl8720dn**
- refactor by bringing this driver more in line with wifinina and espat
- **ssd1306**
- add getter method to the current buffer
- **makeybutton**
- revise to better match the algorithm defined by the original
- **espat,wifinina,rtl8720dn**
- change ssid/pass from const to var
- **bugfixes**
- **microbitmatrix**
- fix inverted axis
- **espat**
- Trim quotes from IP returned by espat's GetDNS()
- **all**
- correct go fmt
- **examples**
- **rtl8720dn**
- remove wifi setting
- add call to optional debug setting
- update all remaining examples for refactored API
0.22.0
---
- **new devices**
- epd: add waveshare 2.9in (v1)
- makeybutton: add driver for MakeyMakey-like button
- **enhancements**
- **rtl8720dn**
- add UDP close function
- improve error handling
- **net/http**
- improve header parsing
- add last-will-and-testament to MQTT
- **net/mqtt**
- adds keepalive pinging, disconnect, and graceful goroutine cleanup
- support for cookies when https
- add support for retained messsages
- **bugfixes**
- irremote: Fix irremote reporting incorrect NEC addresses and command codes (#422)
- net/http: Fix http.Get() with port specification
- **build**
- Makefile recursively finds unit-tests
- switching to GHA
- **updates**
- update tinyfont to v0.3.0
- update tinyfs to v0.2.0
- **examples**
- rtl8720dn: add ./examples/rtl8720dn/version
0.21.0
---
- **new devices**
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018-2023 The TinyGo Authors. All rights reserved.
Copyright (c) 2018-2022 The TinyGo Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
+232 -3
View File
@@ -7,11 +7,240 @@ FMT_PATHS = ./
fmt-check:
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
XTENSA ?= 1
smoke-test:
@mkdir -p build
@go run ./smoketest.go -xtensa=$(XTENSA) smoketest.sh
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/amg88xx
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmi160/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp280/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bmp388/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espconsole/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/esphub/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espstation/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/flash/console/spi
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/hcsr04/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/customchar/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/text/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/hd44780i2c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/hts221/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hub75/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/basic
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/basic
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/pyportal_boing
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/scroll
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/scroll
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/slideshow
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis3dh/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/lps22hb/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/lsm303agr/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mag3110/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017-multiple/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp3008/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp2515/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/servo
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/shtc3/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1331/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7735/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7789/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/thermistor/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-bluefruit ./examples/tone
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/tm1637/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/fourwire/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/pyportal_touchpaint/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl53l1x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd4in2/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/ntpclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/udpstation/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/tcpclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/webclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.bin -target=m5stamp-c3 ./examples/ws2812
@md5sum ./build/test.bin
tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/is31fl3731/main.go
@md5sum ./build/test.hex
ifneq ($(AVR), 0)
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/ws2812
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=digispark ./examples/ws2812
@md5sum ./build/test.hex
endif
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bme280/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/microphone/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/buzzer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/veml6070/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/simple/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/speed/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/simple/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/speed/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nucleo-f103rb ./examples/shiftregister/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=hifive1b ./examples/ssd1351/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis2mdl/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/max72xx/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
@md5sum ./build/test.hex
# tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go
# @md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clkout/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/time/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/tinyfs/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webclient/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webserver/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/mqttsub/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/i2csoft/adt7410/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/basic/
@md5sum ./build/test.elf
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/touchpaint/
@md5sum ./build/test.elf
tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/sx126x/lora_rxtx/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/ssd1289/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.hex -target=pico ./examples/irremote/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=badger2040 ./examples/uc8151/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/scd4x/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
@md5sum ./build/test.uf2
# rwildcard is a recursive version of $(wildcard)
# https://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html
+91 -3
View File
@@ -50,10 +50,98 @@ func main() {
}
```
## Supported devices
## Currently supported devices
There are currently 96 devices supported. For the complete list, please see:
https://tinygo.org/docs/reference/devices/
The following 81 devices are supported.
| Device Name | Interface Type |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
| [ADT7410 I2C Temperature Sensor](https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf) | I2C |
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
| [AHT20 I2C Temperature and Humidity Sensor](http://www.aosong.com/userfiles/files/media/AHT20%20%E8%8B%B1%E6%96%87%E7%89%88%E8%AF%B4%E6%98%8E%E4%B9%A6%20A0%2020201222.pdf) | I2C |
| [AMG88xx 8x8 Thermal camera sensor](https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf) | I2C |
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
| [APDS9960 Digital proximity, ambient light, RGB and gesture sensor](https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf) | I2C |
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
| [AXP192 single Cell Li-Battery and Power System Management](https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf) | I2C |
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
| [BlinkM RGB LED](http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf) | I2C |
| [BME280 humidity/pressure sensor](https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf) | I2C |
| [BMI160 accelerometer/gyroscope](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi160-ds000.pdf) | SPI |
| [BMP180 barometer](https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf) | I2C |
| [BMP280 temperature/barometer](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf) | I2C |
| [BMP388 pressure sensor](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf) | I2C |
| [Buzzer](https://en.wikipedia.org/wiki/Buzzer#Piezoelectric) | GPIO |
| [DHTXX thermometer and humidity sensor](https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf) | GPIO |
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
| [FT6336 touch controller](https://focuslcds.com/content/FT6236.pdf) | I2C |
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
| [HC-SR04 Ultrasonic distance sensor](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf) | GPIO |
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
| [HTS221 digital humidity and temperature sensor](https://www.st.com/resource/en/datasheet/hts221.pdf) | I2C |
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
| [software I2C driver](https://www.ti.com/lit/an/slva704/slva704.pdf) | GPIO |
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
| [INA260 Volt/Amp/Power meter](https://www.ti.com/lit/ds/symlink/ina260.pdf) | I2C |
| [Infrared remote control](https://en.wikipedia.org/wiki/Consumer_IR) | GPIO |
| [IS31FL3731 matrix LED driver](https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf) | I2C |
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
| [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C |
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
| [LPS22HB MEMS nano pressure sensor](https://www.st.com/resource/en/datasheet/dm00140895.pdf) | I2C |
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
| [LSM6DSOX accelerometer](https://www.st.com/resource/en/datasheet/lsm6dsox.pdf) | I2C |
| [LSM6DS3TR accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3tr.pdf) | I2C |
| [LSM303AGR accelerometer](https://www.st.com/resource/en/datasheet/lsm303agr.pdf) | I2C |
| [LSM9DS1 accelerometer](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) | I2C |
| [Makey Button](https://makeymakey.com/) | GPIO |
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
| [MAX7219 & MAX7221 display driver](https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf) | SPI |
| [MCP2515 Stand-Alone CAN Controller with SPI Interface](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Family-Data-Sheet-DS20001801K.pdf) | SPI |
| [MCP3008 analog to digital converter (ADC)](http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf) | SPI |
| [MCP23017 port expander](https://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf) | I2C |
| [Microphone - PDM](https://cdn-learn.adafruit.com/assets/assets/000/049/977/original/MP34DT01-M.pdf) | I2S/PDM |
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
| [RTL8720DN 2.4G/5G Dual Bands Wireless and BLE5.0](https://www.seeedstudio.com/Realtek8720DN-2-4G-5G-Dual-Bands-Wireless-and-BLE5-0-Combo-Module-p-4442.html) | UART |
| [SCD4x CO2 Sensor](https://sensirion.com/media/documents/C4B87CE6/627C2DCD/CD_DS_SCD40_SCD41_Datasheet_D1.pdf) | I2C |
| [Semihosting](https://wiki.segger.com/Semihosting) | Debug |
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
| [SHTC3 Digital Humidity Sensor (RH/T)](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHTC3_Datasheet.pdf) | I2C |
| [SPI NOR Flash Memory](https://en.wikipedia.org/wiki/Flash_memory#NOR_flash) | SPI/QSPI |
| [SPI SDCARD/MMC](https://en.wikipedia.org/wiki/SD_card) | SPI |
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |
| [SSD1351 OLED display](https://download.mikroe.com/documents/datasheets/ssd1351-revision-1.3.pdf) | SPI |
| [ST7735 TFT color display](https://www.crystalfontz.com/controllers/Sitronix/ST7735R/319/) | SPI |
| [ST7789 TFT color display](https://cdn-shop.adafruit.com/product-files/3787/3787_tft_QT154H2201__________20190228182902.pdf) | SPI |
| [Stepper motor "Easystepper" controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
| [Thermistor](https://www.farnell.com/datasheets/33552.pdf) | ADC |
| [TM1637 7-segment LED display](https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_TM1637.pdf) | I2C |
| [TMP102 I2C Temperature Sensor](https://download.mikroe.com/documents/datasheets/tmp102-data-sheet.pdf) | I2C |
| [UC8151 All-in-one driver IC for ESL](https://www.buydisplay.com/download/ic/UC8151C.pdf) | I2C |
| [VEML6070 UV light sensor](https://www.vishay.com/docs/84277/veml6070.pdf) | I2C |
| [VL53L1X time-of-flight distance sensor](https://www.st.com/resource/en/datasheet/vl53l1x.pdf) | I2C |
| [Waveshare 2.13" (B & C) e-paper display](https://www.waveshare.com/w/upload/d/d3/2.13inch-e-paper-b-Specification.pdf) | SPI |
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI |
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-transceiv-ers/sx1261) | SPI |
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
## Contributing
+1
View File
@@ -1,6 +1,7 @@
// Package adt7410 provides a driver for the adt7410 I2C Temperature Sensor.
//
// Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf
//
package adt7410 // import "tinygo.org/x/drivers/adt7410"
import (
+1
View File
@@ -3,6 +3,7 @@
// Datasheet EN: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
//
// Datasheet JP: http://www.analog.com/media/jp/technical-documentation/data-sheets/ADXL345_jp.pdf
//
package adxl345 // import "tinygo.org/x/drivers/adxl345"
import "tinygo.org/x/drivers"
+1
View File
@@ -2,6 +2,7 @@
// a digital proximity, ambient light, RGB and gesture sensor.
//
// Datasheet: https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf
//
package apds9960
import (
+3
View File
@@ -1,7 +1,10 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package apds9960
import "tinygo.org/x/drivers"
// Configure sets up the APDS-9960 device.
func (d *Device) Configure(cfg Configuration) {
// configure device
+1
View File
@@ -1,4 +1,5 @@
//go:build nano_33_ble
// +build nano_33_ble
package apds9960
-172
View File
@@ -1,172 +0,0 @@
// Product: https://ams.com/as5600
// Datasheet: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
package as560x // import tinygo.org/x/drivers/ams560x
import (
"time"
"tinygo.org/x/drivers"
)
// AS5600 includes MPOS & MANG in addition to ZPOS to set a 'narrower angle range'
// ZPOS enables setting the 'zero position' of the device to any RAW_ANGLE value.
// MPOS ('max position') & MANG 'max angle' enable a 'partial range' on the AS5600.
// The value in ANGLE is scaled & adjusted by the device according to ZPOS and MPOS/MANG.
// The entire 12-bit range is 'compressed' into the RAW_ANGLE range of ZPOS->MPOS
// (or ZPOS->ZPOS+MANG) thus enabling a higher resolution for a partial range.
// if ZPOS > MPOS (or ZPOS + MANG > 4095) i.e. the incremental range 'crosses zero'
// then the device will automatically compensate for the correct range.
// For RAW_ANGLE values outside of the partial range, ANGLE will be 'capped' at either
// 0 or 4095, depending on 'which end of the partial range is closer.'
// AS5600Device represents an ams AS5600 device driver accessed over I2C
type AS5600Device struct {
// promote BaseDevice
BaseDevice
}
// NewAS5600 creates a new AS5600Device given an I2C bus
func NewAS5600(bus drivers.I2C) AS5600Device {
// Create base device
baseDev := newBaseDevice(bus)
// Add AS5600 specific registers
baseDev.registers[MPOS] = newI2CRegister(MPOS, 0, 0xfff, 2, reg_read|reg_write|reg_program)
baseDev.registers[MANG] = newI2CRegister(MANG, 0, 0xfff, 2, reg_read|reg_write|reg_program)
// Add AS5600 specific 'virtual registers'
conf, ok := baseDev.registers[CONF]
if ok {
baseDev.registers[PWMF] = newVirtualRegister(conf, 6, 0b11)
baseDev.registers[OUTS] = newVirtualRegister(conf, 4, 0b11)
}
// Return the device
return AS5600Device{baseDev}
}
// Configure sets up the AMS AS5600 sensor device with the given configuration.
func (d *AS5600Device) Configure(cfg Config) error {
// Call the BaseDevice method to do the actual Configure
d.BaseDevice.Configure(cfg)
// For AS5600 devices we need to calculate the maxAngle on startup from ZPOS/MPOS/MANG
// These could have been permanently BURN'ed (by writing BURN register with BURN_ANGLE/BURN_SETTING)
// or may have already been written in previous runs without a power cycle since.
mpos, err := d.ReadRegister(MPOS)
if nil != err {
return err
}
mang, err := d.ReadRegister(MANG)
if nil != err {
return err
}
// Read ZPOS for side effect of caching only so that next calculateEffectiveMaxAngle() can't fail
if _, err = d.ReadRegister(ZPOS); nil != err {
return err
}
if mpos != 0 {
// If MPOS is set, use MPOS regardless of MANG
err = d.calculateEffectiveMaxAngle(MPOS, mpos)
} else if mang != 0 {
// If MANG is set and MPOS == 0, use MANG
err = d.calculateEffectiveMaxAngle(MANG, mang)
} else {
// if neither is set, we have no narrow range
d.maxAngle = NATIVE_ANGLE_RANGE
}
return err
}
// calculateEffectiveMaxAngle calculates d.maxAngle after one of ZPOS/MPOS/MANG have been written
func (d *AS5600Device) calculateEffectiveMaxAngle(register uint8, value uint16) error {
var zpos, mpos uint16 = 0, 0
var err error = nil
switch register {
case MANG:
d.maxAngle = value // The easy case
return nil
case ZPOS:
zpos = value
mpos, err = d.ReadRegister(MPOS)
case MPOS:
mpos = value
zpos, err = d.ReadRegister(ZPOS)
default:
panic("calculateEffectiveMaxAngle() can only work from ZPOS, MPOS or MANG")
}
if nil != err {
return err
}
// MANG is effectively MPOS-ZPOS
mang := int(mpos) - int(zpos)
// correct for mpos < zpos
if mang < 0 {
mang += NATIVE_ANGLE_RANGE
}
d.maxAngle = uint16(mang)
return nil
}
// WriteRegister writes the given value for the given register to the AS560x device via I2C
func (d *AS5600Device) WriteRegister(address uint8, value uint16) error {
// Call the BaseDevice method to do the actual write
if err := d.BaseDevice.WriteRegister(address, value); err != nil {
return err
}
// When either ZPOS/MANG/MPOS are set we need to recalculate maxAngle
// We also may need to invalidate some cached values for the other two registers
recalc := false
switch address {
case ZPOS:
// Setting a new ZPOS invalidates MPOS but not MANG
d.registers[MPOS].invalidate()
recalc = true
case MPOS:
// Setting a new MPOS invalidates MANG but not ZPOS
d.registers[MANG].invalidate()
recalc = true
case MANG:
// Setting a new MANG invalidates MPOS but not ZPOS
d.registers[MPOS].invalidate()
recalc = true
}
if recalc {
// Datasheet tells us to wait at least 1ms before reading back
time.Sleep(time.Millisecond * 10) // conservative wait
return d.calculateEffectiveMaxAngle(address, value)
}
return nil
}
// GetMaxPosition returns the 'max position' (MPOS) in different units
func (d *AS5600Device) GetMaxPosition(units AngleUnit) (uint16, float32, error) {
mpos, err := d.ReadRegister(MPOS)
if nil != err {
return 0, 0.0, err
}
// Convert to requested units
i, f := convertFromNativeAngle(mpos, NATIVE_ANGLE_RANGE, units)
return i, f, nil
}
// SetMaxPosition sets the 'max position' (MPOS) in different units
func (d *AS5600Device) SetMaxPosition(mpos float32, units AngleUnit) error {
return d.WriteRegister(MPOS, convertToNativeAngle(mpos, units))
}
// GetMaxAngle returns the 'max position' (MANG) in different units
func (d *AS5600Device) GetMaxAngle(units AngleUnit) (uint16, float32, error) {
mang, err := d.ReadRegister(MANG)
if nil != err {
return 0, 0.0, err
}
// Convert to requested units
i, f := convertFromNativeAngle(mang, NATIVE_ANGLE_RANGE, units)
return i, f, nil
}
// SetMaxAngle sets the 'max angle' (MANG) in different units
func (d *AS5600Device) SetMaxAngle(mang float32, units AngleUnit) error {
return d.WriteRegister(MANG, convertToNativeAngle(mang, units))
}
-22
View File
@@ -1,22 +0,0 @@
// Product: https://ams.com/as5601
// Datasheet: https://ams.com/documents/20143/36005/AS5601_DS000395_3-00.pdf
package as560x // import tinygo.org/x/drivers/ams560x
import "tinygo.org/x/drivers"
// AS5601Device represents an ams AS5601 device driver accessed over I2C
type AS5601Device struct {
BaseDevice // promote base device
}
// NewAS5601 creates a new AS5601Device given an I2C bus
func NewAS5601(bus drivers.I2C) AS5601Device {
// Create base device
baseDev := newBaseDevice(bus)
// Add AS5601 specific registers
baseDev.registers[ABN] = newI2CRegister(ABN, 0, 0b1111, 1, reg_read|reg_write|reg_program)
baseDev.registers[PUSHTHR] = newI2CRegister(PUSHTHR, 0, 0xff, 1, reg_read|reg_write|reg_program)
// Return the device
return AS5601Device{baseDev}
}
-198
View File
@@ -1,198 +0,0 @@
// Package as560x implements drivers for the ams AS5600/AS5601 on-axis magnetic rotary position sensors
//
// Product Pages:
// AS5600: https://ams.com/as5600
// AS5601: https://ams.com/as5601
//
// Datasheets:
// AS5600: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
// AS5601: https://ams.com/documents/20143/36005/AS5601_DS000395_3-00.pdf
//
package as560x // import tinygo.org/x/drivers/ams560x
import (
"errors"
"tinygo.org/x/drivers"
)
// Config holds the configuration for the AMS AS560x sensor devices.
type Config struct {
// Address is the I2C address of the AS560x device. If left zero this will default to 0x36
Address uint8
}
// MagnetStrength is an enum to indicate the magnetic field strength detected by the AS560x sensors.
type MagnetStrength int
const (
// MagnetTooWeak indicates that the magnet strength is too weak (AGC maximum gain overflow) - move it closer
MagnetTooWeak MagnetStrength = iota - 1
// MagnetOk indicates that the magnet strength is about right.
MagnetOk
// MagnetTooStrong indicates that the magnet strength is too strong (AGC minimum gain overflow) - move it further away
MagnetTooStrong
)
// AngleUnit is an enum to allow the use of different units when reading/writing angles from the AS560x sensors.
type AngleUnit int
const (
// ANGLE_NATIVE uses the device's native angle measurement. i.e. 12-bit integer, 0 <= angle <= 0xfff (4095)
ANGLE_NATIVE AngleUnit = iota
// ANGLE_DEGREES_INT measures angles in degrees using integer arithmetic for speed. i.e. 0 <= angle < 360
ANGLE_DEGREES_INT
// ANGLE_DEGREES_FLOAT measures angles in degrees using floating point (slower). i.e. 0.0 <= angle < 360.0
ANGLE_DEGREES_FLOAT
// ANGLE_RADIANS measures angles in radians using floating point (slower). i.e. 0.0 <= angle < 2 * PI
ANGLE_RADIANS
)
const (
// NATIVE_ANGLE_MAX is the maximum valid value for a native angle for a AS560x device
NATIVE_ANGLE_MAX = (1 << 12) - 1 + iota
// NATIVE_ANGLE_RANGE is the number of unique values for native angles for a AS560x device
NATIVE_ANGLE_RANGE
)
var (
errRegisterNotFound = errors.New("Register not found")
errMaxBurnAngle = errors.New("Max BURN_ANGLE limit reached")
)
// BaseDevice handles the common behaviour between AS5600 & AS5601 devices
type BaseDevice struct {
bus drivers.I2C
address uint8
registers map[uint8]*i2cRegister
maxAngle uint16
}
// newBaseDevice creates a new base device given an I2C bus.
func newBaseDevice(bus drivers.I2C) BaseDevice {
// Add all 'base' registers, common to both AS5600 & AS5601
conf := newI2CRegister(CONF, 0, 0x3fff, 2, reg_read|reg_write|reg_program)
status := newI2CRegister(STATUS, 0, 0xff, 1, reg_read)
regs := map[uint8]*i2cRegister{
ZPOS: newI2CRegister(ZPOS, 0, 0xfff, 2, reg_read|reg_write|reg_program),
CONF: conf,
RAW_ANGLE: newI2CRegister(RAW_ANGLE, 0, 0xfff, 2, reg_read),
ANGLE: newI2CRegister(ANGLE, 0, 0xfff, 2, reg_read),
STATUS: status,
AGC: newI2CRegister(AGC, 0, 0xff, 1, reg_read),
MAGNITUDE: newI2CRegister(MAGNITUDE, 0, 0xfff, 2, reg_read),
BURN: newI2CRegister(BURN, 0, 0xff, 1, reg_write),
// Add common 'virtual registers' These are bitfields within the common registers above
// A virtual register provides a convenient way to access the fields of a registers
// by handling all of the necessary bitfield shifting and masking operations
WD: newVirtualRegister(conf, 13, 0b1),
FTH: newVirtualRegister(conf, 10, 0b111),
SF: newVirtualRegister(conf, 8, 0b11),
HYST: newVirtualRegister(conf, 2, 0b11),
PM: newVirtualRegister(conf, 0, 0b11),
MD: newVirtualRegister(status, 5, 0b1),
ML: newVirtualRegister(status, 4, 0b1),
MH: newVirtualRegister(status, 3, 0b1),
}
return BaseDevice{bus, DefaultAddress, regs, NATIVE_ANGLE_RANGE}
}
// Configure sets up the AMS AS560x sensor device with the given configuration.
func (d *BaseDevice) Configure(cfg Config) {
if cfg.Address == 0 {
cfg.Address = DefaultAddress
}
d.address = cfg.Address
}
// ReadRegister reads the value for the given register from the AS560x device via I2C
func (d *BaseDevice) ReadRegister(address uint8) (uint16, error) {
reg, ok := d.registers[address]
if !ok {
return 0, errRegisterNotFound
}
return reg.read(d.bus, d.address)
}
// WriteRegister writes the given value for the given register to the AS560x device via I2C
func (d *BaseDevice) WriteRegister(address uint8, value uint16) error {
reg, ok := d.registers[address]
if !ok {
return errRegisterNotFound
}
return reg.write(d.bus, d.address, value)
}
// GetZeroPosition returns the 'zero position' (ZPOS) in various units
func (d *BaseDevice) GetZeroPosition(units AngleUnit) (uint16, float32, error) {
zpos, err := d.ReadRegister(ZPOS)
if nil != err {
return 0, 0.0, err
}
// Convert to requested units
i, f := convertFromNativeAngle(zpos, NATIVE_ANGLE_RANGE, units)
return i, f, nil
}
// SetZeroPosition sets the 'zero position' (ZPOS) in various units
func (d *BaseDevice) SetZeroPosition(zpos float32, units AngleUnit) error {
return d.WriteRegister(ZPOS, convertToNativeAngle(zpos, units))
}
// RawAngle reads the (unscaled & unadjusted) RAW_ANGLE register in various units
func (d *BaseDevice) RawAngle(units AngleUnit) (uint16, float32, error) {
angle, err := d.ReadRegister(RAW_ANGLE)
if nil != err {
return 0, 0.0, err
}
// Convert to requested units
i, f := convertFromNativeAngle(angle, NATIVE_ANGLE_RANGE, units)
return i, f, nil
}
// Angle reads the (scaled & adjusted) ANGLE register in various units
func (d *BaseDevice) Angle(units AngleUnit) (uint16, float32, error) {
// ZPOS enables setting the 'zero position' of the device to any RAW_ANGLE value
// ANGLE is RAW_ANGLE adjusted relative to ZPOS.
angle, err := d.ReadRegister(ANGLE)
if nil != err {
return 0, 0.0, err
}
// Convert to requested units
i, f := convertFromNativeAngle(angle, d.maxAngle, units)
return i, f, nil
}
// MagnetStatus reads the STATUS register and reports magnet position characteristics
func (d *BaseDevice) MagnetStatus() (detected bool, strength MagnetStrength, err error) {
status, err := d.ReadRegister(STATUS)
if nil != err {
return false, MagnetOk, err
}
detected = (status & STATUS_MD) != 0
strength = MagnetOk
if (status & STATUS_ML) != 0 {
strength = MagnetTooWeak
} else if (status & STATUS_MH) != 0 {
strength = MagnetTooStrong
}
return
}
// Burn is a convenience method to program the device permanently by writing to the BURN register (limited number of times use!)
func (d *BaseDevice) Burn(burnCmd BURN_CMD) error {
if BURN_ANGLE == burnCmd {
// BURN_ANGLE can only be executed up to 3 times.
// We can check this in advance by reading ZMCO before writing to the BURN register.
numBurns, err := d.ReadRegister(ZMCO)
if nil != err {
return err
}
if numBurns >= BURN_ANGLE_COUNT_MAX {
// We're outta BURNs :(
return errMaxBurnAngle
}
}
return d.WriteRegister(BURN, uint16(burnCmd))
}
-95
View File
@@ -1,95 +0,0 @@
package as560x // import tinygo.org/x/drivers/ams560x
import "math"
// convertFromNativeAngle converts and scales an angle from the device's native 12-bit range to the requested units
func convertFromNativeAngle(angle uint16, maxAngle uint16, units AngleUnit) (uint16, float32) {
// MANG == 0 & MANG == NATIVE_ANGLE_RANGE (1 << 12) mean the same thing: use full circle range
// but the latter makes the maths/code simpler
if 0 == maxAngle {
maxAngle = NATIVE_ANGLE_RANGE
}
switch units {
case ANGLE_NATIVE:
// For native angles, scaling has already been done by the device
return angle, float32(angle)
case ANGLE_DEGREES_INT:
// Convert to degrees using integer arithmetic. Less accuracy but faster
var deg int = 0
if NATIVE_ANGLE_RANGE == maxAngle {
// Simplify the conversion when using the full range
deg = int(angle) * 360 >> 12
} else {
// Using an integer degrees scale with a narrower native range is pointless since we don't
// benefit at all from the increase in native resolution, in fact we LOSE precision.
// Alas, we have to return something
// First get maxAngle on the degrees scale
degMang, _ := convertFromNativeAngle(maxAngle, NATIVE_ANGLE_RANGE, units)
// Now scale angle
deg = int(angle) * int(degMang) / NATIVE_ANGLE_RANGE
}
return uint16(deg), float32(deg)
case ANGLE_DEGREES_FLOAT:
// Convert to degrees using floating point. More accuracy at expense of speed
var degF float32 = 0.0
if NATIVE_ANGLE_RANGE == maxAngle {
// Simplify the conversion when using the full range
degF = float32(angle) * 360.0 / NATIVE_ANGLE_RANGE
} else {
// Scale to degrees using a narrower native range
// First get maxAngle on the degrees scale
_, degMangF := convertFromNativeAngle(maxAngle, NATIVE_ANGLE_RANGE, units)
// Now scale angle
degF = float32(angle) * degMangF / NATIVE_ANGLE_RANGE
}
return uint16(degF), degF
case ANGLE_RADIANS:
// Convert to radians. Can only be done using floating point.
var rad float32 = 0.0
if NATIVE_ANGLE_RANGE == maxAngle {
// Simplify the conversion when using the full range
rad = float32(angle) * 2 * math.Pi / NATIVE_ANGLE_RANGE
} else {
// Scale to radians using a narrower native range
// First get maxAngle on the radians scale
_, radMang := convertFromNativeAngle(maxAngle, NATIVE_ANGLE_RANGE, units)
// Now scale angle
rad = float32(angle) * radMang / NATIVE_ANGLE_RANGE
}
return uint16(rad), rad
default:
panic("Unknown angle measurement unit")
}
}
// convertToNativeAngle converts an angle from the requested units to the device's native 12-bit range.
func convertToNativeAngle(angle float32, units AngleUnit) uint16 {
var pos uint16 = 0
switch units {
case ANGLE_NATIVE:
pos = uint16(angle)
case ANGLE_DEGREES_INT:
fallthrough
case ANGLE_DEGREES_FLOAT:
// Convert from degrees
angle = float32(math.Mod(float64(angle), 360.0))
if angle < 0.0 {
angle += 360.0
}
pos = uint16(math.Round(float64(angle) * NATIVE_ANGLE_RANGE / 360.0))
case ANGLE_RADIANS:
// Convert from radians
const circRad = 2.0 * math.Pi
angle = float32(math.Mod(float64(angle), circRad))
if angle < 0.0 {
angle += circRad
}
pos = uint16(math.Round(float64(angle) * NATIVE_ANGLE_RANGE / circRad))
default:
panic("Unknown angle measurement unit")
}
if pos > NATIVE_ANGLE_MAX {
pos = NATIVE_ANGLE_MAX
}
return pos
}
-169
View File
@@ -1,169 +0,0 @@
package as560x // import tinygo.org/x/drivers/ams560x
import (
"encoding/binary"
"errors"
"tinygo.org/x/drivers"
)
// registerAttributes is a bitfield of attributes for a register
type registerAttributes uint8
const (
// reg_read indicates that the register is readable
reg_read registerAttributes = 1 << iota
// reg_write indicates that the register is writeable
reg_write
// reg_program indicates that the register can be permanently programmed ('BURNed')
reg_program
)
var (
errRegisterNotReadable = errors.New("Register is not readable")
errRegisterNotWriteable = errors.New("Register is not writeable")
)
// i2cRegister encapsulates the address, structure and read/write logic for a register on a AS560x device
type i2cRegister struct {
// host is the 'host register' for virtual registers. Physical/root registers have this set to self
host *i2cRegister
// address is the i2c address of the register. For 2-byte (word) addresses it's the low byte which holds the MSBs
address uint8
// shift is the number of bits the value is 'left shifted' into the register byte/word (0-15)
shift uint16
// mask is a bitwise mask applied to the register AFTER 'right shifting' to mask the register value
mask uint16
// num_bytes is the width of the register in bytes, 1 or 2.
num_bytes uint8
// attributes holds the register attributes. A bitfield of REG_xyz constants
attributes registerAttributes
// cached indicates whether we are holding a cached value of the register in value
cached bool
// value can be used as a 'cache' of the register's value for writeable registers.
value uint16
}
// newI2CRegister returns a pointer to a new i2cRegister with no cached value
func newI2CRegister(address uint8, shift uint16, mask uint16, num_bytes uint8, attributes registerAttributes) *i2cRegister {
reg := &i2cRegister{
address: address,
shift: shift,
mask: mask,
num_bytes: num_bytes,
attributes: attributes,
}
// root registers host themselves
reg.host = reg
return reg
}
// newVirtualRegister returns a pointer to a new i2cRegister with the given host register and shift/mask.
func newVirtualRegister(host *i2cRegister, shift uint16, mask uint16) *i2cRegister {
return &i2cRegister{
host: host,
address: host.address,
shift: shift,
mask: mask,
num_bytes: host.num_bytes,
attributes: host.attributes,
}
}
// invalidate invalidates any cached value for the register and forces an I2C read on the next read()
func (r *i2cRegister) invalidate() {
r.host.cached = false
r.host.value = 0
}
// readShiftAndMask is an internal method to read a value for the register over the given I2C bus from the device with the given address applying the given shift and mask
func (r *i2cRegister) readShiftAndMask(bus drivers.I2C, deviceAddress uint8, shift uint16, mask uint16) (uint16, error) {
if r.host.attributes&reg_read == 0 {
return 0, errRegisterNotReadable
}
// Only read over I2C if we don't have the host register value cached
var val uint16 = r.host.value
if !r.host.cached {
// To avoid an alloc we always use an array of 2 bytes
var buffer [2]byte
var buf []byte
if r.host.num_bytes < 2 {
buf = buffer[:1]
} else {
buf = buffer[:]
}
// Read the host register over I2C
err := bus.ReadRegister(deviceAddress, r.host.address, buf)
if nil != err {
return 0, err
}
// Unpack data from I2C
if r.host.num_bytes > 1 {
val = binary.BigEndian.Uint16(buf)
} else {
val = uint16(buf[0])
}
// cache this value if the host register is writeable. Note we cache the entire buffer without applying shift/mask
if r.host.attributes&reg_write != 0 {
r.host.value = val
r.host.cached = true
}
}
// Shift and mask the value before returning
val >>= shift
val &= mask
return val, nil
}
// read reads a value for the register over the given I2C bus from the device with the given address.
func (r *i2cRegister) read(bus drivers.I2C, deviceAddress uint8) (uint16, error) {
return r.readShiftAndMask(bus, deviceAddress, r.shift, r.mask)
}
// write writes a value for the register over the given I2C bus to the device with the given address.
func (r *i2cRegister) write(bus drivers.I2C, deviceAddress uint8, value uint16) error {
if r.host.attributes&reg_write == 0 {
return errRegisterNotWriteable
}
var newValue uint16 = 0
// Data sheet tells us to do a read first, modify only the desired bits and then write back
// since (quote:) 'Blank fields may contain factory settings'
// We will also need to do this anyway to support virtualRegister mappings on some registers
// (e.g. CONF/STATUS)
if (r.host.attributes & reg_read) > 0 { // not all registers are readable, e.g. BURN
// read the host register's entire host byte/word, regardless of shift & mask
readValue, error := r.readShiftAndMask(bus, deviceAddress, 0, 0xffff)
if error != nil {
return error
}
// Zero-out ONLY the relevant bits in newValue we just read
readValue &= (0xffff ^ (r.mask << r.shift))
newValue = readValue
}
// Mask the new value and shift it into place
value &= r.mask
value <<= r.shift
// OR the masked & shifted value back into newValue to be written
newValue |= value
// Pack newValue into a byte buffer to write. To avoid an alloc we always use an array of 2 bytes
var buffer [2]byte
var buf []byte
if r.host.num_bytes < 2 {
buf = buffer[:1]
buf[0] = uint8(newValue & 0xff)
} else {
buf = buffer[:]
binary.BigEndian.PutUint16(buf, newValue)
}
// Write the register from the buffer over I2C
err := bus.WriteRegister(deviceAddress, r.host.address, buf)
// after successful I2C write, cache this value if the host register (if also readable)
// Note we cache the entire buffer without applying shift/mask
if nil == err && r.host.attributes&reg_read != 0 {
r.host.value = newValue
r.host.cached = true
}
return err
}
-208
View File
@@ -1,208 +0,0 @@
package as560x // import tinygo.org/x/drivers/ams560x
// DefaultAddress is the default I2C address of the AMS AS560x sensors (0x36).
const DefaultAddress uint8 = 0x36
// AS560x common device registers
const (
// ZMCO contains the number of times a BURN_ANGLE command has been executed (max 3 burns)
ZMCO = 0x00
// ZPOS is the zero (start) position in RAW_ANGLE terms.
ZPOS = 0x01
// CONF supports custom config. Raw 14-bit register. See datasheet for mapping or use 'virtual registers' below.
CONF = 0x07
// STATUS indicates magnet position. Encapsulates MD, ML & MH. See also 'virtual registers' below.
STATUS = 0x0b
// RAW_ANGLE is the raw unscaled & unadjusted angle (12 bit: 0-4095/0xfff)
RAW_ANGLE = 0x0c
// ANGLE is RAW_ANGLE scaled & adjusted according to ZPOS (and MPOS/MANG on AS5600). (12 bit: 0-4095/0xfff)
ANGLE = 0x0e
// AGC is the Automatic Gain Control based on temp, airgap etc. 0-255 @ 5V, 0-128 @ 3.3V.
AGC = 0x1a
// MAGNITUDE indicates the magnitude value of the internal CORDIC output. See datasheet for more info.
MAGNITUDE = 0x1b
// BURN performs permanent programming of some registers. See BURN_XYZ cmd constants below for commands.
BURN = 0xff
)
// AS5600 specific registers
const (
// MPOS is the maximum position in RAW_ANGLE terms. With ZPOS, defines a 'narrower angle' for higher resolution.
MPOS = 0x03
// MANG is the maximum angle. With ZPOS, defines a 'narrower angle' for higher resolution.
MANG = 0x05
)
// AS5601 specific registers
const (
// ABN. See datasheet for mapping
ABN = 0x09
// PUSHTHR. Configures push-button function. See datasheet and AGC
PUSHTHR = 0x0a
)
// 'Virtual Registers' (VRs) are bitfields within the registers above.
// These are not real register addresses recognized by the chip,
// but they are recognized by the driver for convenience.
// virtualRegisterStartAddress defines the start of the virtual register address range.
const virtualRegisterStartAddress = 0xa0
const (
// VRs for CONF
// WD is a Virtual Register for the Watchdog timer. See WATCHDOG_TIMER consts.
WD = iota + virtualRegisterStartAddress
// FTH is a Virtual Register for the Fast Filter Threshold. See FAST_FILTER_THRESHOLD consts.
FTH
// SF is a Virtual Register for the Slow Filter. See SLOW_FILTER_RESPONSE consts.
SF
// PWMF is a Virtual Register for PWM Frequency (AS5600 ONLY). See PWM_FREQUENCY consts.
PWMF
// OUTS is a Virtual Register for the Output Stage (AS5600 ONLY). See OUTPUT_STAGE consts.
OUTS
// HYST is a Virtual Register for Hysteresis. See HYSTERESIS consts.
HYST
// PM is a Virtual Register for the Power Mode. See POWER_MODE consts.
PM
// VRs for STATUS (0 = unset, 1 = set)
// MD is a Virtual Register for the 'Magnet was detected' flag.
MD
// ML is a Virtual Register for the 'AGC maximum gain overflow' a.k.a 'magnet too weak' flag.
ML
// MH is a Virtual Register for the 'AGC minimum gain overflow' a.k.a 'magnet too strong' flag.
MH
)
// POWER_MODE values for the PM component of CONF (and the PM VR)
const (
// PM_NOM is the normal 'always on' power mode. No polling, max 6.5mA current
PM_NOM = iota
// PM_LPM1 is Low Power Mode 1. 5ms polling, max 3.4mA current
PM_LPM1
// PM_LPM2 is Low Power Mode 2. 20ms polling, max 1.8mA current
PM_LPM2
// PM_LPM3 is Low Power Mode 3. 100ms polling, max 1.5mA current
PM_LPM3
)
// HYSTERESIS values for the HYST component of CONF (and the HYST VR)
const (
// HYST_OFF disables any hysteresis of the output
HYST_OFF = iota
// HYST_1LSB enables output hysteresis using 1 LSB
HYST_1LSB
// HYST_2LSB enables output hysteresis using 2 LSBs
HYST_2LSB
// HYST_3LSB enables output hysteresis using 3 LSBs
HYST_3LSB
)
// OUTPUT_STAGE values for the OUTS component of CONF (and the OUTS VR - AS5600 ONLY)
const (
// OS_ANALOG_FULL_RANGE enables analog output with full range (0%-100% VDD)
OS_ANALOG_FULL_RANGE = iota
// OS_ANALOG_REDUCED_RANGE enables analog output with reduced range (10%-90% VDD)
OS_ANALOG_REDUCED_RANGE
// OS_DIGITAL_PWM enables digital PWM output. Frequency determined by PWMF
OS_DIGITAL_PWM
)
// PWM_FREQUENCY values for the PWMF component of CONF (and the PWMF VR - ASS5600 ONLY)
const (
// PWMF_115_HZ enables PWM at 115 Hz
PWMF_115_HZ = iota
// PWMF_230_HZ enables PWM at 230 Hz
PWMF_230_HZ
// PWMF_460_HZ enables PWM at 460 Hz
PWMF_460_HZ
// PWMF_920_HZ enables PWM at 920 Hz
PWMF_920_HZ
)
// SLOW_FILTER_RESPONSE values for the SF (slow filter) component of CONF (and the SF VR)
const (
// SF_16X enables a 16x Slow Filter step response
SF_16X = iota
// SF_8X enables a 8x Slow Filter step response
SF_8X
// SF_4X enables a 4x Slow Filter step response
SF_4X
// SF_2X enables a 2x Slow Filter step response
SF_2X
)
// FAST_FILTER_THRESHOLD values for the FTH (fast filter threshold) component of CONF (and the FTH VR)
const (
// FTH_NONE disables the fast filter (slow filter only)
FTH_NONE = iota
// FTH_6LSB enables a fast filter threshold with 6 LSBs
FTH_6LSB
// FTH_7LSB enables a fast filter threshold with 7 LSBs
FTH_7LSB
// FTH_9LSB enables a fast filter threshold with 9 LSBs
FTH_9LSB
// FTH_18LSB enables a fast filter threshold with 18 LSBs
FTH_18LSB
// FTH_21LSB enables a fast filter threshold with 21 LSBs
FTH_21LSB
// FTH_24LSB enables a fast filter threshold with 24 LSBs
FTH_24SB
// FTH_10LSB enables a fast filter threshold with 10 LSBs
FTH_10LSB
)
// WATCHDOG_TIMER values for the WD component of CONF (and the WD VR)
const (
// WD_OFF disables the Watchdog Timer
WD_OFF = iota
// WD_ON enables the Watchdog Timer (automatic entry into LPM3 low-power mode enabled)
WD_ON
)
// constants for the raw STATUS register bitfield value.
const (
// STATUS_MH is set in STATUS when the magnet field is too strong (AGC minimum gain overflow)
STATUS_MH = 1 << (iota + 3)
// STATUS_ML is set in STATUS when the magnet field is too weak (AGC maximum gain overflow)
STATUS_ML
// STATUS_MD is set n STATUS when the magnet is detected. Doesn't seem to work with some units.
STATUS_MD
)
// ABN_MAPPING values for the ABN register (AS5601 ONLY)
const (
// ABN_8 configures 8 output positions (61 Hz)
ABN_8 = iota
// ABN_16 configures 16 output positions (122 Hz)
ABN_16
// ABN_32 configures 32 output positions (244 Hz)
ABN_32
// ABN_64 configures 64 output positions (488 Hz)
ABN_64
// ABN_128 configures 128 output positions (976 Hz)
ABN_128
// ABN_256 configures 256 output positions (1.95 KHz)
ABN_256
// ABN_512 configures 512 output positions (3.9 KHz)
ABN_512
// ABN_1024 configures 1024 output positions (7.8 KHz)
ABN_1024
// ABN_2048 configures 2048 output positions (15.6 KHz)
ABN_2048
)
// BURN_CMD is a command to write to the BURN register.
type BURN_CMD uint16
const (
// BURN_ANGLE is the value to write to BURN to permanently program ZPOS & MPOS (Max 3 times!)
BURN_ANGLE BURN_CMD = 0x80
// BURN_SETTING is the value to write to BURN to permanently program MANG & CONF (ONCE ONLY!)
BURN_SETTING BURN_CMD = 0x40
)
// BURN_ANGLE_COUNT_MAX is a constant for the maximum number of times a BURN_ANGLE command can be executed. Compare this with ZMCO
const BURN_ANGLE_COUNT_MAX uint16 = 3
+1
View File
@@ -3,6 +3,7 @@
//
// http://www.x-powers.com/en.php/Info/product_detail/article_id/29
// Datasheet: https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf
//
package axp192 // import "tinygo.org/x/drivers/axp192"
import (
+1
View File
@@ -2,6 +2,7 @@
//
// Datasheet:
// https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf
//
package bh1750 // import "tinygo.org/x/drivers/bh1750"
import (
+1
View File
@@ -1,6 +1,7 @@
// Package blinkm implements a driver for the BlinkM I2C RGB LED.
//
// Datasheet: http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf
//
package blinkm // import "tinygo.org/x/drivers/blinkm"
import "tinygo.org/x/drivers"
+7 -117
View File
@@ -3,11 +3,11 @@
//
// Datasheet:
// https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
//
package bme280
import (
"math"
"time"
"tinygo.org/x/drivers"
)
@@ -34,27 +34,11 @@ type calibrationCoefficients struct {
h6 int8
}
type Oversampling byte
type Mode byte
type FilterCoefficient byte
type Period byte
// Config contains settings for filtering, sampling, and modes of operation
type Config struct {
Pressure Oversampling
Temperature Oversampling
Humidity Oversampling
Period Period
Mode Mode
IIR FilterCoefficient
}
// Device wraps an I2C connection to a BME280 device.
type Device struct {
bus drivers.I2C
Address uint16
calibrationCoefficients calibrationCoefficients
Config Config
}
// New creates a new BME280 connection. The I2C bus must already be
@@ -68,34 +52,9 @@ func New(bus drivers.I2C) Device {
}
}
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration is the Indoor Navigation settings
// from the BME280 datasheet.
// Configure sets up the device for communication and
// read the calibration coefficientes.
func (d *Device) Configure() {
d.ConfigureWithSettings(Config{})
}
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration if config is left at defaults is
// the Indoor Navigation settings from the BME280 datasheet.
func (d *Device) ConfigureWithSettings(config Config) {
d.Config = config
// If config is not initialized, use Indoor Navigation defaults.
if d.Config == (Config{}) {
d.Config = Config{
Mode: ModeNormal,
Period: Period0_5ms,
Temperature: Sampling2X,
Humidity: Sampling1X,
Pressure: Sampling16X,
IIR: Coeff16,
}
}
var data [24]byte
err := d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION, data[:])
@@ -135,18 +94,10 @@ func (d *Device) ConfigureWithSettings(config Config) {
d.calibrationCoefficients.h4 = 0 + (int16(h2lsb[3]) << 4) | (int16(h2lsb[4] & 0x0F))
d.calibrationCoefficients.h5 = 0 + (int16(h2lsb[5]) << 4) | (int16(h2lsb[4]) >> 4)
d.Reset()
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{0x3f})
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{0xB7})
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{0x00})
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{byte(d.Config.Period<<5) | byte(d.Config.IIR<<2)})
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{byte(d.Config.Humidity)})
// Normal mode, start measuring now
if d.Config.Mode == ModeNormal {
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
}
// Connected returns whether a BME280 has been found.
@@ -162,20 +113,6 @@ func (d *Device) Reset() {
d.bus.WriteRegister(uint8(d.Address), CMD_RESET, []byte{0xB6})
}
// SetMode can set the device to Sleep, Normal or Forced mode
//
// Calling this method is optional, Configure can be used to set the
// initial mode if no mode change is desired. This method is most
// useful to switch between Sleep and Normal modes.
func (d *Device) SetMode(mode Mode) {
d.Config.Mode = mode
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d *Device) ReadTemperature() (int32, error) {
data, err := d.readData()
@@ -212,8 +149,7 @@ func (d *Device) ReadHumidity() (int32, error) {
// ReadAltitude returns the current altitude in meters based on the
// current barometric pressure and estimated pressure at sea level.
// Calculation is based on code from Adafruit BME280 library
//
// https://github.com/adafruit/Adafruit_BME280_Library
// https://github.com/adafruit/Adafruit_BME280_Library
func (d *Device) ReadAltitude() (alt int32, err error) {
mPa, _ := d.ReadPressure()
atmP := float32(mPa) / 100000
@@ -250,16 +186,6 @@ func readIntLE(msb byte, lsb byte) int16 {
// readData does a burst read from 0xF7 to 0xF0 according to the datasheet
// resulting in an slice with 8 bytes 0-2 = pressure / 3-5 = temperature / 6-7 = humidity
func (d *Device) readData() (data [8]byte, err error) {
if d.Config.Mode == ModeForced {
// Write the CTRL_MEAS register to trigger a measurement
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
time.Sleep(d.measurementDelay())
}
err = d.bus.ReadRegister(uint8(d.Address), REG_PRESSURE, data[:])
if err != nil {
println(err)
@@ -330,39 +256,3 @@ func (d *Device) calculateHumidity(data [8]byte, tFine int32) int32 {
return int32(100 * h)
}
// measurementDelay returns how much time each measurement will take
// on the device.
//
// This is used in forced mode to wait until a measurement is complete.
func (d *Device) measurementDelay() time.Duration {
const MeasOffset = 1250
const MeasDur = 2300
const HumMeasOffset = 575
const MeasScalingFactor = 1000
// delay is based on over-sampling rate - this table converts from
// setting to number samples
sampleRateConv := []int{0, 1, 2, 4, 8, 16}
tempOsr := 16
if d.Config.Temperature <= Sampling16X {
tempOsr = sampleRateConv[d.Config.Temperature]
}
presOsr := 16
if d.Config.Temperature <= Sampling16X {
presOsr = sampleRateConv[d.Config.Pressure]
}
humOsr := 16
if d.Config.Temperature <= Sampling16X {
humOsr = sampleRateConv[d.Config.Humidity]
}
max_delay := ((MeasOffset + (MeasDur * tempOsr) +
((MeasDur * presOsr) + HumMeasOffset) +
((MeasDur * humOsr) + HumMeasOffset)) / MeasScalingFactor)
return time.Duration(max_delay) * time.Millisecond
}
-44
View File
@@ -20,50 +20,6 @@ const (
CHIP_ID = 0x60
)
// Increasing sampling rate increases precision but also the wait time for measurements. The datasheet has a table of
// suggested values for oversampling, output data rates, and iir filter coefficients by use case.
const (
SamplingOff Oversampling = iota
Sampling1X
Sampling2X
Sampling4X
Sampling8X
Sampling16X
)
// In normal mode (the default) the sensor takes masurements periodically. In forced
// mode, the sensor takes a measurement only when requested.
//
// For use-cases with infrequent sampling, forced mode is more power efficient.
const (
ModeNormal Mode = 0x03
ModeForced Mode = 0x01
ModeSleep Mode = 0x00
)
// IIR filter coefficients, higher values means steadier measurements but slower reaction times
const (
Coeff0 FilterCoefficient = iota
Coeff2
Coeff4
Coeff8
Coeff16
)
// Period of standby in normal mode which controls how often measurements are taken
//
// Note Period10ms and Period20ms are out of sequence, but are per the datasheet
const (
Period0_5ms Period = 0b000
Period62_5ms = 0b001
Period125ms = 0b010
Period250ms = 0b011
Period500ms = 0b100
Period1000ms = 0b101
Period10ms = 0b110
Period20ms = 0b111
)
const (
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
)
+1 -16
View File
@@ -3,10 +3,10 @@
//
// Datasheet:
// https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
//
package bmp180 // import "tinygo.org/x/drivers/bmp180"
import (
"math"
"time"
"tinygo.org/x/drivers"
@@ -124,21 +124,6 @@ func (d *Device) ReadPressure() (pressure int32, err error) {
return 1000 * (p + ((x1 + x2 + 3791) >> 4)), nil
}
// ReadAltitude returns the current altitude in meters based on the
// current barometric pressure and estimated pressure at sea level.
// Calculation is based on code from Adafruit BME280 library
//
// https://github.com/adafruit/Adafruit_BME280_Library
func (d *Device) ReadAltitude() (int32, error) {
mPa, err := d.ReadPressure()
if err != nil {
return 0, err
}
atmP := float32(mPa) / 100000
return int32(44330.0 * (1.0 - math.Pow(float64(atmP/SEALEVEL_PRESSURE), 0.1903))), nil
}
// rawTemp returns the sensor's raw values of the temperature
func (d *Device) rawTemp() (int32, error) {
d.bus.WriteRegister(uint8(d.Address), REG_CTRL, []byte{CMD_TEMP})
-4
View File
@@ -28,7 +28,3 @@ const (
// ULTRAHIGHRESOLUTION is the highest oversampling mode of the pressure measurement.
ULTRAHIGHRESOLUTION
)
const (
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
)
+1 -6
View File
@@ -1,4 +1,5 @@
// Package buzzer provides a very simplistic driver for a connected buzzer or low-fidelity speaker.
//
package buzzer // import "tinygo.org/x/drivers/buzzer"
import (
@@ -54,12 +55,6 @@ func (l *Device) Tone(hz, duration float64) (err error) {
tempo := ((60 / l.BPM) * (duration * 1000))
// no tone during rest, just let the duration pass.
if hz == Rest {
time.Sleep(time.Duration(tempo) * time.Millisecond)
return
}
for i := 0.0; i < tempo*1000; i += tone * 2.0 {
if err = l.On(); err != nil {
return
+3 -3
View File
@@ -1,9 +1,9 @@
package buzzer
const (
Whole = 4.0
Half = 2.0
Quarter = 1.0
Whole = 4
Half = 2
Quarter = 1
Eighth = 0.500
)
-54
View File
@@ -1,54 +0,0 @@
#include <stdint.h>
#include <stdbool.h>
// Loop the given times, where one loop takes four CPU cycles.
bool tinygo_drivers_sleep(uint32_t cycles) {
// In this function, a [n] comment indicates the number of cycles an
// instruction or a set of instructions take. This is typically 1 for most
// arithmetic instructions, and a bit more for branches.
#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__
// Inline assembly for Cortex-M0/M0+/M3/M4/M7.
// The Cortex-M0 (but not M0+) takes one more cycle, so is off by 12.5%.
// Others should be basically cycle-accurate (with a slight overhead to
// calculate the number of cycles). Unfortunately, there doesn't appear to
// be a preprocessor macro to detect the Cortex-M0 specifically (although we
// could rely on macros like NRF51).
// Each loop takes 8 cycles (5 nops, 1 sub, and 2 for the branch).
uint32_t loops = (cycles + 7) / 8;
__asm__ __volatile__(
"1:\n\t"
"nop\n\t" // [5] nops
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"subs %[loops], #1\n\t" // [1]
"bne 1b" // [1-4], at least 2 cycles if taken
: [loops]"+r"(loops)
);
return true;
#elif __XTENSA__
// Inline assembly for Xtensa.
// I don't know exactly how many cycles a branch takes, so I've taken a
// conservative guess and assume it takes only one cycle. In practice, it's
// probably more than that.
uint32_t loops = (cycles + 7) / 8;
__asm__ __volatile__(
"1:\n\t"
"nop\n\t" // [6] nops
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"addi %[loops], %[loops], -1\n\t" // [1]
"bnez %[loops], 1b" // [1?]
: [loops]"+r"(loops)
);
return true;
#else
// Unknown architecture, so fall back to time.Sleep.
return false;
#endif
}
-57
View File
@@ -1,57 +0,0 @@
package delay
import (
"machine"
"time"
)
/*
#include <stdint.h>
#include <stdbool.h>
bool tinygo_drivers_sleep(uint32_t ticks);
*/
import "C"
// Sleep for a very precise short duration by busy-waiting for the given time.
// This is not an efficient way to sleep: it will needlessly burn cycles while
// sleeping. But it is useful for sleeping for a very short duration, for
// example for bit-banged protocols.
//
// Longer durations (longer than a few milliseconds) will be handled by calling
// time.Sleep instead.
//
// This function should be called with a constant duration value, in which case
// the call will typically be fully inlined and only take up around nine
// instructions for the entire loop.
//
//go:inline
func Sleep(duration time.Duration) {
if time.Duration(uint32(duration)&0xff_ffff) != duration {
// This is a long duration (more than 16ms) which shouldn't be done by
// busy-waiting.
time.Sleep(duration)
return
}
// Calculate the number of cycles we should sleep:
// cycles = duration * freq / 1e9
// Avoiding a 64-bit division:
// cycles = duration * (freq/1000_000) / 1000
//
// This assumes:
// * The CPU frequency is a constant and can trivially be
// const-propagated, therefore the divide by 1000_000 is done at compile
// time.
// * The CPU frequency is a multiple of 1000_000, which is true for most
// chips (examples: 16MHz, 48MHz, 120MHz, etc).
// * The division by 1000 can be done efficiently (Cortex-M3 and up), or
// can be fully const-propagated.
// * The CPU frequency is lower than 256MHz. If it is higher, long sleep
// times (1-16ms) may not work correctly.
cycles := uint32(duration) * (machine.CPUFrequency() / 1000_000) / 1000
slept := C.tinygo_drivers_sleep(cycles)
if !slept {
// Fallback for platforms without inline assembly support.
time.Sleep(duration)
}
}
+1
View File
@@ -1,4 +1,5 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
+1
View File
@@ -1,4 +1,5 @@
//go:build mimxrt1062 || stm32f405 || atsamd51 || stm32f103xx || k210 || stm32f407
// +build mimxrt1062 stm32f405 atsamd51 stm32f103xx k210 stm32f407
package dht // import "tinygo.org/x/drivers/dht"
+1
View File
@@ -1,4 +1,5 @@
//go:build !mimxrt1062 && !stm32f405 && !atsamd51 && !stm32f103xx && !k210 && !stm32f407
// +build !mimxrt1062,!stm32f405,!atsamd51,!stm32f103xx,!k210,!stm32f407
package dht // import "tinygo.org/x/drivers/dht"
+3 -3
View File
@@ -1,4 +1,5 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
@@ -10,7 +11,6 @@ package dht // import "tinygo.org/x/drivers/dht"
import (
"machine"
"runtime/interrupt"
"time"
)
@@ -160,8 +160,8 @@ func (t *device) read() error {
// interrupts
func receiveSignals(pin machine.Pin, result []counter) {
i := uint8(0)
mask := interrupt.Disable()
defer interrupt.Restore(mask)
machine.UART1.Interrupt.Disable()
defer machine.UART1.Interrupt.Enable()
for ; i < 40; i++ {
result[i*2] = expectChange(pin, false)
result[i*2+1] = expectChange(pin, true)
+1
View File
@@ -1,4 +1,5 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
+1
View File
@@ -1,4 +1,5 @@
//go:build tinygo
// +build tinygo
package dht // import "tinygo.org/x/drivers/dht"
-16
View File
@@ -12,19 +12,3 @@ type Displayer interface {
// Display sends the buffer (if any) to the screen.
Display() error
}
// Rotation is how much a display has been rotated. Displays can be rotated, and
// sometimes also mirrored.
type Rotation uint8
// Clockwise rotation of the screen.
const (
Rotation0 = iota
Rotation90
Rotation180
Rotation270
Rotation0Mirror
Rotation90Mirror
Rotation180Mirror
Rotation270Mirror
)
+8 -7
View File
@@ -3,22 +3,22 @@
//
// Here is an example in TinyGo that uses the BMP180 digital barometer:
//
// package main
// package main
//
// import (
// import (
// "time"
// "machine"
//
// "tinygo.org/x/drivers/bmp180"
// )
// "tinygo.org/x/drivers/bmp180"
// )
//
// func main() {
// func main() {
// machine.I2C0.Configure(machine.I2CConfig{})
// sensor := bmp180.New(machine.I2C0)
// sensor.Configure()
//
// connected := sensor.Connected()
// if !connected {
// connected := sensor.Connected()
// if !connected {
// println("BMP180 not detected")
// return
// }
@@ -38,4 +38,5 @@
// Each individual driver is contained within its own sub-package within this package and
// there are no interdependencies in order to minimize the final size of compiled code that
// uses any of these drivers.
//
package drivers // import "tinygo.org/x/drivers"
+1
View File
@@ -2,6 +2,7 @@
//
// Datasheet:
// https://datasheets.maximintegrated.com/en/ds/DS1307.pdf
//
package ds1307 // import "tinygo.org/x/drivers/ds1307"
import (
-89
View File
@@ -1,89 +0,0 @@
// Package ds18b20 provides a driver for the DS18B20 digital thermometer
//
// Datasheet:
// https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
package ds18b20 // import "tinygo.org/x/drivers/ds18b20"
import (
"errors"
)
// Device ROM commands
const (
CONVERT_TEMPERATURE uint8 = 0x44
READ_SCRATCHPAD uint8 = 0xBE
WRITE_SCRATCHPAD uint8 = 0x4E
)
type OneWireDevice interface {
Write(uint8)
Read() uint8
Select([]uint8) error
Сrc8([]uint8, int) uint8
}
// Device wraps a connection to an 1-Wire devices.
type Device struct {
owd OneWireDevice
}
// Errors list
var (
errReadTemperature = errors.New("Error: DS18B20. Read temperature error: CRC mismatch.")
)
func New(owd OneWireDevice) Device {
return Device{
owd: owd,
}
}
// Configure. Initializes the device, left for compatibility reasons.
func (d Device) Configure() {}
// ThermometerResolution sets thermometer resolution from 9 to 12 bits
func (d Device) ThermometerResolution(romid []uint8, resolution uint8) {
if 9 <= resolution && resolution <= 12 {
d.owd.Select(romid)
d.owd.Write(WRITE_SCRATCHPAD) // send three data bytes to scratchpad (TH, TL, and config)
d.owd.Write(0xFF) // to TH
d.owd.Write(0x00) // to TL
d.owd.Write(((resolution - 9) << 5) | 0x1F) // to resolution config
}
}
// RequestTemperature sends request to device
func (d Device) RequestTemperature(romid []uint8) {
d.owd.Select(romid)
d.owd.Write(CONVERT_TEMPERATURE)
}
// ReadTemperatureRaw returns the raw temperature.
// ScratchPad memory map:
// byte 0: Temperature LSB
// byte 1: Temperature MSB
func (d Device) ReadTemperatureRaw(romid []uint8) ([]uint8, error) {
spb := make([]uint8, 9) // ScratchPad buffer
d.owd.Select(romid)
d.owd.Write(READ_SCRATCHPAD)
for i := 0; i < 9; i++ {
spb[i] = d.owd.Read()
}
if d.owd.Сrc8(spb, 8) != spb[8] {
return nil, errReadTemperature
}
return spb[:2:2], nil
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d Device) ReadTemperature(romid []uint8) (int32, error) {
raw, err := d.ReadTemperatureRaw(romid)
if err != nil {
return 0, err
}
t := int32(uint16(raw[0]) | uint16(raw[1])<<8)
if t&0x8000 == 0x8000 {
t -= 0x10000
}
return (t * 625 / 10), nil
}
+2 -36
View File
@@ -73,17 +73,7 @@ func (d *Device) SetRunning(isRunning bool) error {
return nil
}
// SetTime sets the date and time in the DS3231. The DS3231 hardware supports
// only a 2-digit year field, so the current year will be stored as an offset
// from the year 2000, which supports the year 2000 until 2100.
//
// The DS3231 also supports a one-bit 'century' flag which is set by the chip
// when the year field rolls over from 99 to 00. The current code interprets
// this flag to be the year 2100, which appears to extend the range of years
// until the year 2200. However the DS3231 does not incorporate the 'century'
// flag in its leap year calculation, so it will incorrectly identify the year
// 2100 as a leap year, causing it to increment from 2100-02-28 to 2100-02-29
// instead of 2100-03-01.
// SetTime sets the date and time in the DS3231
func (d *Device) SetTime(dt time.Time) error {
data := []byte{0}
err := d.bus.ReadRegister(uint8(d.Address), REG_STATUS, data)
@@ -102,10 +92,6 @@ func (d *Device) SetTime(dt time.Time) error {
data[2] = uint8ToBCD(uint8(dt.Hour()))
year := uint8(dt.Year() - 2000)
// This code interprets the centuryFlag to be the year 2100. Warning: The
// DS3231 does not incorporate the centuryFlag in its leap year calculation.
// It will increment from 2100-02-28 to 2100-02-29, which is incorrect because
// the year 2100 is not a leap year in the Gregorian calendar.
centuryFlag := uint8(0)
if year >= 100 {
year -= 100
@@ -154,27 +140,7 @@ func (d *Device) ReadTemperature() (int32, error) {
if err != nil {
return 0, err
}
return milliCelsius(data[0], data[1]), nil
}
// milliCelsius converts the raw temperature bytes (msb and lsb) from the DS3231
// into a 32-bit signed integer in units of milli Celsius (1/1000 deg C).
//
// According to the DS3231 datasheet: "Temperature is represented as a 10-bit
// code with a resolution of 0.25 deg C and is accessible at location 11h and
// 12h. The temperature is encoded in two's complement format. The upper 8 bits,
// the integer portion, are at location 11h and the lower 2 bits, the fractional
// portion, are in the upper nibble at location 12h."
//
// In other words, the msb and lsb bytes should be treated as a signed 16-bit
// integer in units of (1/256 deg C). It is possible to convert this into a
// 16-bit signed integer in units of centi Celsius (1/100 deg C) with no loss of
// precision or dynamic range. But for backwards compatibility, let's instead
// convert this into a 32-bit signed integer in units of milli Celsius.
func milliCelsius(msb uint8, lsb uint8) int32 {
t256 := int16(uint16(msb)<<8 | uint16(lsb))
t1000 := int32(t256) / 64 * 250
return t1000
return int32(data[0])*1000 + int32((data[1]>>6)*25)*10, nil
}
// uint8ToBCD converts a byte to BCD for the DS3231
-76
View File
@@ -1,76 +0,0 @@
package ds3231
import (
"testing"
)
func TestPositiveMilliCelsius(t *testing.T) {
t1000 := milliCelsius(0, 0)
if t1000 != 0 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0, 0b01000000)
if t1000 != 250 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0, 0b10000000)
if t1000 != 500 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0, 0b11000000)
if t1000 != 750 {
t.Fatal(t1000)
}
t1000 = milliCelsius(1, 0b00000000)
if t1000 != 1000 {
t.Fatal(t1000)
}
t1000 = milliCelsius(2, 0b00000000)
if t1000 != 2000 {
t.Fatal(t1000)
}
// highest temperature is 127.750C
t1000 = milliCelsius(0x7f, 0b11000000)
if t1000 != 127750 {
t.Fatal(t1000)
}
}
func TestNegativeMilliCelsius(t *testing.T) {
t1000 := milliCelsius(0xff, 0b11000000)
if t1000 != -250 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0xff, 0b10000000)
if t1000 != -500 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0xff, 0b01000000)
if t1000 != -750 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0xff, 0b00000000)
if t1000 != -1000 {
t.Fatal(t1000)
}
t1000 = milliCelsius(0xfe, 0b00000000)
if t1000 != -2000 {
t.Fatal(t1000)
}
// lowest temperature is -128.000C
t1000 = milliCelsius(0x80, 0b00000000)
if t1000 != -128000 {
t.Fatal(t1000)
}
}
+1
View File
@@ -15,6 +15,7 @@
//
// AT command set:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
package espat // import "tinygo.org/x/drivers/espat"
import (
+1 -1
View File
@@ -29,7 +29,7 @@ func (d *Device) GetDNS(domain string) (string, error) {
return "", errors.New("Invalid domain lookup result")
}
res := strings.Split(r[1], "\r\n")
return strings.Trim(res[0], `"`), nil
return res[0], nil
}
// ConnectTCPSocket creates a new TCP socket connection for the ESP8266/ESP32.
-66
View File
@@ -1,66 +0,0 @@
package main
import (
"machine"
"machine/usb/hid/mouse"
"math"
"time"
"tinygo.org/x/drivers/as560x"
)
func main() {
// Let's use the AS5600 to make the world's most useless mouse with just a single X-axis & no buttons (!)
machine.I2C0.Configure(machine.I2CConfig{
Frequency: machine.TWI_FREQ_400KHZ,
SDA: machine.GPIO4,
SCL: machine.GPIO5,
})
as5600 := as560x.NewAS5600(machine.I2C0)
as5600.Configure(as560x.Config{})
mouse := mouse.New()
lastAngle := -1
for {
time.Sleep(time.Millisecond * 10)
// Get the magnet status of the AS5600
magnetDetected, magnetStrength, err := as5600.MagnetStatus()
if err != nil {
continue
}
// Get the raw angle from the AS5600
angle, _, err := as5600.RawAngle(as560x.ANGLE_NATIVE)
if err != nil {
continue
}
str := ""
if !magnetDetected {
str += "NOT "
}
str += "detected. Strength is "
switch magnetStrength {
case as560x.MagnetTooWeak:
str += "too weak"
case as560x.MagnetTooStrong:
str += "too strong"
default:
str += "ok"
}
println("Raw angle:", angle, "Magnet was", str)
if lastAngle != -1 {
diff := int(angle) - lastAngle
// correct the zero crossover glitch
if diff < -0xc00 {
diff += 0xfff
} else if diff > 0xc00 {
diff -= 0xfff
}
// debounce the noise (could use the sensor's filters/hysteresis instead?)
if math.Abs(float64(diff)) > 2 {
// move the mouse x-axis in response to the AS5600
mouse.Move(diff, 0)
}
}
lastAngle = int(angle)
}
}
-3
View File
@@ -27,9 +27,6 @@ func main() {
pressure, _ := sensor.ReadPressure()
println("Pressure", float32(pressure)/100000, "hPa")
altitude, _ := sensor.ReadAltitude()
println("Altitude", altitude, "meters")
time.Sleep(2 * time.Second)
}
}
-17
View File
@@ -1,17 +0,0 @@
package main
import (
"time"
"tinygo.org/x/drivers/delay"
)
func main() {
time.Sleep(time.Second) // wait for a serial console
start := time.Now()
for i := 0; i < 2000; i++ {
delay.Sleep(50 * time.Microsecond)
}
duration := time.Since(start)
println("sleep of 2000*50µs (100ms) took:", duration.String())
}
-58
View File
@@ -1,58 +0,0 @@
package main
import (
"encoding/hex"
"machine"
"time"
"tinygo.org/x/drivers/onewire"
"tinygo.org/x/drivers/ds18b20"
)
func main() {
// Define pin for DS18B20
pin := machine.D2
ow := onewire.New(pin)
romIDs, err := ow.Search(onewire.SEARCH_ROM)
if err != nil {
println(err)
}
sensor := ds18b20.New(ow)
for {
time.Sleep(3 * time.Second)
println()
println("Device:", machine.Device)
println()
println("Request Temperature.")
for _, romid := range romIDs {
println("Sensor RomID: ", hex.EncodeToString(romid))
sensor.RequestTemperature(romid)
}
// wait 750ms or more for DS18B20 convert T
time.Sleep(1 * time.Second)
println()
println("Read Temperature")
for _, romid := range romIDs {
raw, err := sensor.ReadTemperatureRaw(romid)
if err != nil {
println(err)
}
println()
println("Sensor RomID: ", hex.EncodeToString(romid))
println("Temperature Raw value: ", hex.EncodeToString(raw))
t, err := sensor.ReadTemperature(romid)
if err != nil {
println(err)
}
println("Temperature in celsius milli degrees (°C/1000): ", t)
}
}
}
+4 -5
View File
@@ -6,6 +6,7 @@
//
// More information on the Espressif AT command set at:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
package main
import (
@@ -18,11 +19,9 @@ import (
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
var (
// access point info
ssid string
pass string
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
+4 -5
View File
@@ -3,6 +3,7 @@
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
//
package main
import (
@@ -16,11 +17,9 @@ import (
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
var (
// access point info
ssid string
pass string
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
+4 -5
View File
@@ -3,6 +3,7 @@
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
//
package main
import (
@@ -13,11 +14,9 @@ import (
"tinygo.org/x/drivers/net"
)
var (
// access point info
ssid string
pass string
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the listener aka "hub". Replace with your own info.
const hubIP = "0.0.0.0"
+5 -6
View File
@@ -7,7 +7,8 @@
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
@@ -19,11 +20,9 @@ import (
"tinygo.org/x/drivers/net/mqtt"
)
var (
// access point info
ssid string
pass string
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
+5 -6
View File
@@ -7,7 +7,8 @@
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
@@ -20,11 +21,9 @@ import (
"tinygo.org/x/drivers/net/mqtt"
)
var (
// access point info
ssid string
pass string
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the MQTT broker to use. Replace with your own info.
//const server = "tcp://test.mosquitto.org:1883"
+4 -5
View File
@@ -3,6 +3,7 @@
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
//
package main
import (
@@ -13,11 +14,9 @@ import (
"tinygo.org/x/drivers/net"
)
var (
// access point info
ssid string
pass string
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the server aka "hub". Replace with your own info.
const serverIP = "0.0.0.0"
+1
View File
@@ -1,4 +1,5 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
@@ -1,4 +1,5 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
-39
View File
@@ -1,39 +0,0 @@
package main
import (
"machine"
"time"
"image/color"
"tinygo.org/x/drivers/gc9a01"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 80000000,
})
display := gc9a01.New(machine.SPI0, machine.P6, machine.P7, machine.P8, machine.P9)
display.Configure(gc9a01.Config{Orientation: gc9a01.HORIZONTAL, Width: 240, Height: 240})
width, height := display.Size()
white := color.RGBA{255, 255, 255, 255}
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
green := color.RGBA{0, 255, 0, 255}
black := color.RGBA{0, 0, 0, 255}
display.FillScreen(black)
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
for {
time.Sleep(time.Hour)
}
}
+3
View File
@@ -1,4 +1,5 @@
//go:build atsamd21
// +build atsamd21
package initdisplay
@@ -8,6 +9,8 @@ import (
"tinygo.org/x/drivers/ili9341"
)
var ()
func InitDisplay() *ili9341.Device {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
+1
View File
@@ -1,4 +1,5 @@
//go:build feather_m0 || feather_m4 || feather_m4_can || feather_nrf52840 || feather_nrf52840_sense || feather_stm32f405 || feather_rp2040
// +build feather_m0 feather_m4 feather_m4_can feather_nrf52840 feather_nrf52840_sense feather_stm32f405 feather_rp2040
package initdisplay
+1
View File
@@ -1,4 +1,5 @@
//go:build m5stack
// +build m5stack
package initdisplay
@@ -1,4 +1,5 @@
//go:build m5stack_core2
// +build m5stack_core2
package initdisplay
+1
View File
@@ -1,4 +1,5 @@
//go:build pyportal
// +build pyportal
package initdisplay
@@ -1,4 +1,5 @@
//go:build wioterminal
// +build wioterminal
package initdisplay
-52
View File
@@ -1,52 +0,0 @@
# AT-CMD implementation of at-lora command set
This example implements the AT command set as used by Seeed in the LoRa-E5 series of boards, but in the form of a TinyGo program that provides a serial interface.
See https://files.seeedstudio.com/products/317990687/res/LoRa-E5%20AT%20Command%20Specification_V1.0%20.pdf for more information.
```
$ tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
+AT: OK
+VER: 0.0.1 (sx127x v18)
```
# Building
Run the following commands from the main `drivers` directory.
## Simulator
Builds/flashes atcmd console application with simulator instead of actual LoRa radio.
```
tinygo flash -target pico ./examples/lora/lorawan/atcmd/
```
## PyBadge with LoRa Featherwing
Builds/flashes atcmd console application on PyBadge using LoRa Featherwing (RFM95/SX1276).
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/atcmd/
```
## LoRa-E5
Builds/flashes atcmd console application on Lora-E5 using onboard SX126x.
```
tinygo flash -target lorae5 ./examples/lora/lorawan/atcmd/
```
## Joining a Public Lorawan Network
```
AT+ID=DevEui,0101010101010101
AT+ID=AppEui,0123012301230213
AT+KEY=APPKEY,AEAEAEAEAEAEAEAAEAEAEAEAEAEAAEAE
AT+LW=NET,ON
AT+JOIN
```
AT+LW=NET,(ON|OFF) command changes Lora Sync Word to connect on public network(ON) or private networks(OFF)
-496
View File
@@ -1,496 +0,0 @@
package main
import (
"encoding/hex"
"strings"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora/lorawan"
)
// Use to test if connection to module is OK.
func quicktest() {
writeCommandOutput("AT", "OK")
}
// Check firmware version.
func version() {
writeCommandOutput("VER", common.CurrentVersion()+" ("+common.FirmwareVersion()+")")
}
// Use to check the ID of the LoRaWAN module, or change the ID.
func id(args string) error {
cmd := "ID"
// look for comma in args
param, val, hasComma := strings.Cut(args, ",")
if hasComma {
// set
data := strings.Trim(val, "\"'")
// convert data from hex formatted string
data = strings.ReplaceAll(data, " ", "")
hexdata, err := hex.DecodeString(data)
if err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
switch param {
case "DevAddr":
if err := session.SetDevAddr(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
case "DevEui":
if err := otaa.SetDevEUI(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
case "AppEui":
if err := otaa.SetAppEUI(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
default:
return errInvalidCommand
}
return nil
}
// get
switch param {
case "DevAddr":
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
case "DevEui":
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
case "AppEui":
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
default:
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
}
return nil
}
// Use to reset the module. If module returns error, then reset function is invalid.
func reset() error {
radio.Reset()
writeCommandOutput("RESET", "OK")
return nil
}
// Use to send string format frame which is no need to be confirmed by the server.
func msg(data string) error {
cmd := "MSG"
writeCommandOutput(cmd, "Start")
if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send string format frame which must be confirmed by the server
func cmsg(data string) error {
cmd := "CMSG"
writeCommandOutput(cmd, "Start")
if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
// TODO: confirmation
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send hex format frame which is no need to be confirmed by the server
func msghex(data string) error {
cmd := "MSGHEX"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send hex format frame which must be confirmed by the server.
func cmsghex(data string) error {
cmd := "CMSGHEX"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send string format LoRaWAN proprietary frames
func pmsg(data string) error {
cmd := "PMSG"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send hex format LoRaWAN proprietary frames.
func pmsghex(data string) error {
cmd := "PMSGHEX"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Set PORT number which will be used by MSG/CMSG/MSGHEX/CMSGHEX command to send
// message, port number should range from 1 to 255. User should refer to LoRaWAN
// specification to choose port.
func port(p string) error {
cmd := "PMSG"
writeCommandOutput(cmd, p)
return nil
}
// Set ADR function of LoRaWAN module
func adr(state string) error {
cmd := "ADR"
writeCommandOutput(cmd, state)
return nil
}
// Use LoRaWAN defined DRx to set datarate of LoRaWAN AT modem.
func dr(rate string) error {
cmd := "DR"
writeCommandOutput(cmd, rate)
return nil
}
// Channel Configuration
func ch(channel string) error {
cmd := "CH"
writeCommandOutput(cmd, channel)
return nil
}
// Set and Check Power
func power(setting string) error {
cmd := "POWER"
writeCommandOutput(cmd, setting)
return nil
}
// Unconfirmed message repeats times.
func rept(setting string) error {
cmd := "REPT"
writeCommandOutput(cmd, setting)
return nil
}
// Confirmed message retry times. Valid range 0~254,
// if retry times is less than 2, only one message will
// be sent. Random delay 3 - 10s between each retry
// (band duty cycle limitation has the priority)
func retry(setting string) error {
cmd := "RETRY"
writeCommandOutput(cmd, setting)
return nil
}
func rxwin2(setting string) error {
cmd := "RXWIN2"
writeCommandOutput(cmd, setting)
return nil
}
func rxwin1(setting string) error {
cmd := "RXWIN1"
writeCommandOutput(cmd, setting)
return nil
}
func key(setting string) error {
cmd := "KEY"
// look for comma in args
param, val, hasComma := strings.Cut(setting, ",")
if hasComma {
// set
data := strings.Trim(val, "\"'")
// convert data from hex formatted string
data = strings.ReplaceAll(data, " ", "")
hexdata, err := hex.DecodeString(data)
if err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
switch param {
case "APPKEY":
if err := otaa.SetAppKey(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "APPKEY, "+otaa.GetAppKey())
default:
return errInvalidCommand
}
}
// cannot get keys
return errInvalidCommand
}
func fdefault(setting string) error {
cmd := "FDEFAULT"
writeCommandOutput(cmd, "OK")
return nil
}
func mode(setting string) error {
cmd := "MODE"
writeCommandOutput(cmd, setting)
return nil
}
func join(setting string) error {
// TODO: check that DevEUI, AppEUI, and AppKey have values
cmd := "JOIN"
writeCommandOutput(cmd, "Starting")
if err := lorawan.Join(otaa, session); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Network joined")
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
writeCommandOutput(cmd, "NetID, "+otaa.GetNetID())
writeCommandOutput(cmd, "NwkSKey, "+session.GetNwkSKey())
writeCommandOutput(cmd, "AppSKey, "+session.GetAppSKey())
writeCommandOutput(cmd, "Done")
return nil
}
func beacon(setting string) error {
cmd := "BEACON"
writeCommandOutput(cmd, "Starting")
writeCommandOutput(cmd, "Done")
return nil
}
func class(setting string) error {
cmd := "CLASS"
writeCommandOutput(cmd, "Starting")
writeCommandOutput(cmd, "Done")
return nil
}
func delay(setting string) error {
cmd := "DELAY"
writeCommandOutput(cmd, setting)
return nil
}
func lw(setting string) error {
cmd := "LW"
param, val, hasComma := strings.Cut(setting, ",")
if hasComma {
if param == "NET" {
if val == "ON" {
lorawan.SetPublicNetwork(true)
} else {
lorawan.SetPublicNetwork(false)
}
}
}
writeCommandOutput(cmd, setting)
return nil
}
func wdt(setting string) error {
cmd := "WDT"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func lowpower(setting string) error {
cmd := "LOWPOWER"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func vdd(setting string) error {
cmd := "VDD"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func temp(setting string) error {
cmd := "TEMP"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func rtc(setting string) error {
cmd := "RTC"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func eeprom(setting string) error {
cmd := "EEPROM"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func uartcmd(setting string) error {
cmd := "UART"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func test(setting string) error {
cmd := "TEST"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func log(setting string) error {
cmd := "LOG"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func send(data string) error {
cmd := "SEND"
writeCommandOutput(cmd, "Start")
// remove leading/trailing quotes
data = strings.Trim(data, "\"'")
if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Done")
return nil
}
func sendhex(data string) error {
cmd := "SENDHEX"
writeCommandOutput(cmd, "Start")
// remove leading/trailing quotes
data = strings.Trim(data, "\"'")
// convert data from hex formatted string
data = strings.ReplaceAll(data, " ", "")
payload, err := hex.DecodeString(data)
if err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
if err := radio.Tx(payload, defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Done")
return nil
}
func recv(setting string) error {
cmd := "RECV"
data, err := common.Lorarx()
if err != nil {
writeCommandOutput(cmd, "ERROR "+err.Error())
return err
}
writeCommandOutput(cmd, string(data))
return nil
}
func recvhex(setting string) error {
cmd := "RECVHEX"
data, err := common.Lorarx()
if err != nil {
writeCommandOutput(cmd, "ERROR "+err.Error())
return err
}
writeCommandOutput(cmd, string(data))
return nil
}
func crlf() {
uart.Write([]byte("\r\n"))
}
func writeCommandOutput(cmd, data string) {
uart.Write([]byte("+" + cmd + ": "))
uart.Write([]byte(data))
crlf()
}
-79
View File
@@ -1,79 +0,0 @@
// AT command set console running on the device UART to communicate with
// an attached LoRa device.
//
// Computer <-> UART <-> MCU <-> SPI <-> SX126x/SX127x
//
// Connect using default baudrate for this hardware, 8-N-1 with your terminal program.
// For details on the AT command set, see:
// https://files.seeedstudio.com/products/317990687/res/LoRa-E5%20AT%20Command%20Specification_V1.0%20.pdf
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/lora/lorawan"
"tinygo.org/x/drivers/lora/lorawan/region"
)
// change these to test a different UART or pins if available
var (
uart = machine.Serial
tx = machine.UART_TX_PIN
rx = machine.UART_RX_PIN
input = make([]byte, 0, 64)
radio lora.Radio
session *lorawan.Session
otaa *lorawan.Otaa
defaultTimeout uint32 = 1000
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
var err error
radio, err = common.SetupLora()
if err != nil {
fail(err.Error())
}
session = &lorawan.Session{}
otaa = &lorawan.Otaa{}
lorawan.UseRadio(radio)
lorawan.UseRegionSettings(region.EU868())
for {
if uart.Buffered() > 0 {
data, _ := uart.ReadByte()
switch data {
case 13:
// return key
if err := parse(input); err != nil {
uart.Write([]byte("ERROR: "))
uart.Write([]byte(err.Error()))
crlf()
}
input = input[:0]
default:
// just capture the character
input = append(input, data)
}
}
time.Sleep(10 * time.Millisecond)
}
}
func fail(msg string) {
for {
uart.Write([]byte(msg))
crlf()
time.Sleep(time.Minute)
}
}
-115
View File
@@ -1,115 +0,0 @@
package main
import (
"errors"
"strings"
)
var (
errInvalidCommand = errors.New("Invalid command")
)
func parse(data []byte) error {
switch {
case len(data) < 2, string(data[0:2]) != "AT":
return errInvalidCommand
case len(data) == 2:
// just the AT command by itself
quicktest()
case len(data) < 6 || data[2] != '+':
return errInvalidCommand
default:
// parse the rest of the command
cmd, args, _ := strings.Cut(string(data[3:]), "=")
return parseCommand(cmd, args)
}
return nil
}
func parseCommand(cmd, args string) error {
switch cmd {
case "VER":
version()
case "ID":
id(args)
case "RESET":
reset()
case "MSG":
msg(args)
case "CMSG":
cmsg(args)
case "MSGHEX":
msghex(args)
case "CMSGHEX":
cmsghex(args)
case "PMSG":
pmsg(args)
case "PMSGHEX":
pmsg(args)
case "PORT":
port(args)
case "ADR":
adr(args)
case "DR":
dr(args)
case "CH":
ch(args)
case "POWER":
power(args)
case "REPT":
rept(args)
case "RETRY":
retry(args)
case "RXWIN2":
rxwin2(args)
case "RXWIN1":
rxwin1(args)
case "KEY":
key(args)
case "FDEFAULT":
fdefault(args)
case "MODE":
mode(args)
case "JOIN":
join(args)
case "BEACON":
join(args)
case "CLASS":
class(args)
case "DELAY":
delay(args)
case "LW":
lw(args)
case "WDT":
wdt(args)
case "LOWPOWER":
lowpower(args)
case "VDD":
vdd(args)
case "TEMP":
temp(args)
case "RTC":
rtc(args)
case "EEPROM":
eeprom(args)
case "UART":
uartcmd(args)
case "TEST":
test(args)
case "LOG":
log(args)
case "RECV":
recv(args)
case "RECVHEX":
recvhex(args)
case "SEND":
send(args)
case "SENDHEX":
sendhex(args)
default:
return errInvalidCommand
}
return nil
}
@@ -1,44 +0,0 @@
# Simple Lorawan example
This demo code will connect Lorawan network and send sample uplink message
You may change your Lorawan keys (AppEUI, DevEUI, AppKEY) in key-default.go
```
$ tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
Lorawan Simple Demo
Start Lorawan Join sequence
loraConnect: Connected !
```
# Building
## Simulator
```
tinygo flash -target pico ./examples/lora/lorawan/basic-demo
```
## PyBadge with LoRa Featherwing
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/basic-demo
```
## LoRa-E5
```
tinygo flash -target lorae5 ./examples/lora/lorawan/basic-demo
```
## Enable debugging
You can also enable some debug logs with ldflags :
```
$ tinygo build -ldflags="-X 'main.debug=true'" -target=lorae5
```
@@ -1,17 +0,0 @@
//go:build !customkeys
package main
import (
"tinygo.org/x/drivers/lora/lorawan"
)
// These are sample keys, so the example builds
// Either change here, or create a new go file and use customkeys build tag
func setLorawanKeys() {
otaa.SetAppEUI([]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
otaa.SetDevEUI([]uint8{0xB3, 0xD5, 0x41, 0x00, 0x0A, 0xF1, 0xA4, 0x45})
otaa.SetAppKey([]uint8{0x12, 0x22, 0xA3, 0xFF, 0x0C, 0x7B, 0x76, 0x7B, 0x8F, 0xD3, 0x12, 0x4F, 0xCE, 0x7A, 0x32, 0x16})
lorawan.SetPublicNetwork(true)
}
-109
View File
@@ -1,109 +0,0 @@
// Simple code for connecting to Lorawan network and uploading sample payload
package main
import (
"errors"
"strconv"
"time"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/lora/lorawan"
"tinygo.org/x/drivers/lora/lorawan/region"
)
var debug string
const (
LORAWAN_JOIN_TIMEOUT_SEC = 180
LORAWAN_RECONNECT_DELAY_SEC = 15
LORAWAN_UPLINK_DELAY_SEC = 60
)
var (
radio lora.Radio
session *lorawan.Session
otaa *lorawan.Otaa
)
func loraConnect() error {
start := time.Now()
var err error
for time.Since(start) < LORAWAN_JOIN_TIMEOUT_SEC*time.Second {
println("Trying to join network")
err = lorawan.Join(otaa, session)
if err == nil {
println("Connected to network !")
return nil
}
println("Join error:", err, "retrying in", LORAWAN_RECONNECT_DELAY_SEC, "sec")
time.Sleep(time.Second * LORAWAN_RECONNECT_DELAY_SEC)
}
err = errors.New("Unable to join Lorawan network")
println(err.Error())
return err
}
func failMessage(err error) {
println("FATAL:", err)
for {
}
}
func main() {
println("*** Lorawan basic join and uplink demo ***")
// Board specific Lorawan initialization
var err error
radio, err = common.SetupLora()
if err != nil {
failMessage(err)
}
// Required for LoraWan operations
session = &lorawan.Session{}
otaa = &lorawan.Otaa{}
// Connect the lorawan with the Lora Radio device.
lorawan.UseRadio(radio)
lorawan.UseRegionSettings(region.EU868())
// Configure AppEUI, DevEUI, APPKey, and public/private Lorawan Network
setLorawanKeys()
if debug != "" {
println("main: Network joined")
println("main: DevEui, " + otaa.GetDevEUI())
println("main: AppEui, " + otaa.GetAppEUI())
println("main: DevAddr, " + otaa.GetAppKey())
}
// Try to connect Lorawan network
if err := loraConnect(); err != nil {
failMessage(err)
}
if debug != "" {
println("main: NetID, " + otaa.GetNetID())
println("main: NwkSKey, " + session.GetNwkSKey())
println("main: AppSKey, " + session.GetAppSKey())
println("main: Done")
}
// Try to periodicaly send an uplink sample message
upCount := 1
for {
payload := "Hello TinyGo #" + strconv.Itoa(upCount)
if err := lorawan.SendUplink([]byte(payload), session); err != nil {
println("Uplink error:", err)
} else {
println("Uplink success, msg=", payload)
}
println("Sleeping for", LORAWAN_UPLINK_DELAY_SEC, "sec")
time.Sleep(time.Second * LORAWAN_UPLINK_DELAY_SEC)
upCount++
}
}
@@ -1,14 +0,0 @@
//go:build featherwing
package common
import "machine"
var (
// We assume LoRa Featherwing module with sx127x is connected to PyBadge
rstPin = machine.D11
csPin = machine.D10
dio0Pin = machine.D6
dio1Pin = machine.D9
spi = machine.SPI0
)
-13
View File
@@ -1,13 +0,0 @@
//go:build lgt92
package common
import "machine"
var (
rstPin = machine.PB0
csPin = machine.PA15
dio0Pin = machine.PC13
dio1Pin = machine.PB10
spi = machine.SPI0
)
-10
View File
@@ -1,10 +0,0 @@
package common
import (
"errors"
)
var (
errRadioNotFound = errors.New("radio not found")
errRxTimeout = errors.New("radio RX timeout")
)
-40
View File
@@ -1,40 +0,0 @@
//go:build !featherwing && !lgt92 && !stm32wlx && !sx126x
package common
import "tinygo.org/x/drivers/lora"
// do simulator setup here
func SetupLora() (lora.Radio, error) {
return &SimLoraRadio{}, nil
}
type SimLoraRadio struct {
}
func (sr *SimLoraRadio) Reset() {
}
func (sr *SimLoraRadio) Tx(pkt []uint8, timeoutMs uint32) error {
return nil
}
func (sr *SimLoraRadio) Rx(timeoutMs uint32) ([]uint8, error) {
return nil, nil
}
func (sr *SimLoraRadio) SetFrequency(freq uint32) {}
func (sr *SimLoraRadio) SetIqMode(mode uint8) {}
func (sr *SimLoraRadio) SetCodingRate(cr uint8) {}
func (sr *SimLoraRadio) SetBandwidth(bw uint8) {}
func (sr *SimLoraRadio) SetCrc(enable bool) {}
func (sr *SimLoraRadio) SetSpreadingFactor(sf uint8) {}
func (sr *SimLoraRadio) LoraConfig(cnf lora.Config) {}
func FirmwareVersion() string {
return "simulator " + CurrentVersion()
}
func Lorarx() ([]byte, error) {
return nil, nil
}
-49
View File
@@ -1,49 +0,0 @@
//go:build stm32wlx
package common
import (
"machine"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/sx126x"
)
const (
FREQ = 868100000
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx126x.Device
)
var spi = machine.SPI3
func newRadioControl() sx126x.RadioController {
return sx126x.NewRadioControl()
}
// do sx126x setup here
func SetupLora() (lora.Radio, error) {
loraRadio = sx126x.New(spi)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create radio controller for target
loraRadio.SetRadioController(newRadioControl())
if state := loraRadio.DetectDevice(); !state {
return nil, errRadioNotFound
}
return loraRadio, nil
}
func FirmwareVersion() string {
return "sx126x"
}
func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
}
-53
View File
@@ -1,53 +0,0 @@
//go:build !stm32wlx && sx126x
package common
import (
"machine"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/sx126x"
)
const (
FREQ = 868100000
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx126x.Device
)
var (
spi = machine.SPI0
nssPin, busyPin, dio1Pin = machine.GP17, machine.GP10, machine.GP11
rxPin, txLowPin, txHighPin = machine.GP13, machine.GP12, machine.GP12
)
func newRadioControl() sx126x.RadioController {
return sx126x.NewRadioControl(nssPin, busyPin, dio1Pin, rxPin, txLowPin, txHighPin)
}
// do sx126x setup here
func SetupLora() (lora.Radio, error) {
loraRadio = sx126x.New(spi)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create radio controller for target
loraRadio.SetRadioController(newRadioControl())
if state := loraRadio.DetectDevice(); !state {
return nil, errRadioNotFound
}
return loraRadio, nil
}
func FirmwareVersion() string {
return "sx126x"
}
func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
}
-47
View File
@@ -1,47 +0,0 @@
//go:build featherwing || lgt92
package common
import (
"strconv"
"machine"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/sx127x"
)
const (
FREQ = 868100000
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx127x.Device
)
// do sx127x setup here
func SetupLora() (lora.Radio, error) {
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
spi.Configure(machine.SPIConfig{Frequency: 500000, Mode: 0})
loraRadio = sx127x.New(spi, rstPin)
loraRadio.SetRadioController(sx127x.NewRadioControl(csPin, dio0Pin, dio1Pin))
loraRadio.Reset()
if state := loraRadio.DetectDevice(); !state {
return nil, errRadioNotFound
}
return loraRadio, nil
}
func FirmwareVersion() string {
v := loraRadio.GetVersion()
return "sx127x v" + strconv.Itoa(int(v))
}
func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
}
-7
View File
@@ -1,7 +0,0 @@
package common
const VERSION = "0.0.1"
func CurrentVersion() string {
return VERSION
}
+2 -3
View File
@@ -9,7 +9,7 @@ import (
var (
led machine.Pin = machine.LED
button machine.Pin = machine.D10
button machine.Pin = machine.BUTTON
key *makeybutton.Button
)
@@ -25,7 +25,6 @@ func main() {
case makeybutton.Released:
led.Low()
}
// the more frequent the more responsive
time.Sleep(50 * time.Millisecond)
time.Sleep(100 * time.Millisecond)
}
}
+1
View File
@@ -2,6 +2,7 @@
// to read data from the onboard MEMS microphone.
//
// Uses ideas from the https://github.com/adafruit/Adafruit_CircuitPlayground repo.
//
package main
import (
-22
View File
@@ -1,22 +0,0 @@
// Connects to an MPU6886 I2C accelerometer/gyroscope.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/mpu6886"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
accel := mpu6886.New(machine.I2C0)
accel.Configure(mpu6886.Config{})
for {
x, y, z, _ := accel.ReadAcceleration()
println(x, y, z)
time.Sleep(time.Millisecond * 100)
}
}
-40
View File
@@ -1,40 +0,0 @@
package main
import (
"encoding/hex"
"time"
"tinygo.org/x/drivers/onewire"
)
func main() {
pin := machine.D2
ow := onewire.New(pin)
for {
time.Sleep(3 * time.Second)
println()
println("Device:", machine.Device)
romIDs, err := ow.Search(onewire.SEARCH)
if err != nil {
println(err)
}
for _, romid := range romIDs {
println(hex.EncodeToString(romid))
}
if len(romIDs) == 1 {
// only 1 device on bus
r, err := ow.ReadAddress()
if err != nil {
println(err)
}
println(hex.EncodeToString(r))
}
}
}
-66
View File
@@ -1,66 +0,0 @@
// Connects to an QMI8658C I2C accelerometer/gyroscope and print the read data.
// This example was made with the "WaveShare RP2040 Round LCD 1.28in" in mind.
// For more infor about this development board:
// https://www.waveshare.com/wiki/RP2040-LCD-1.28
package main
import (
"machine"
"time"
imu "tinygo.org/x/drivers/qmi8658c"
)
func main() {
i2c := machine.I2C1
// This is the default pinout for the "WaveShare RP2040 Round LCD 1.28in"
err := i2c.Configure(machine.I2CConfig{
SDA: machine.GP6,
SCL: machine.GP7,
Frequency: 100000,
})
if err != nil {
println("unable to configure I2C:", err)
return
}
// Create a new device
d := imu.New(i2c)
// Check if the device is connected
if !d.Connected() {
println("unable to connect to sensor")
return
}
// This IMU has multiple configurations like output data rate, multiple
// measurements scales, low pass filters, low power modes, all the vailable
// values can be found in the datasheet and were defined at registers file.
// This is the default configuration which will be used if the `nil` value
// is passed do the `Configure` method.
config := imu.Config{
SPIMode: imu.SPI_4_WIRE,
SPIEndian: imu.SPI_BIG_ENDIAN,
SPIAutoInc: imu.SPI_AUTO_INC,
AccEnable: imu.ACC_ENABLE,
AccScale: imu.ACC_8G,
AccRate: imu.ACC_NORMAL_1000HZ,
AccLowPass: imu.ACC_LOW_PASS_2_62,
GyroEnable: imu.GYRO_FULL_ENABLE,
GyroScale: imu.GYRO_512DPS,
GyroRate: imu.GYRO_1000HZ,
GyroLowPass: imu.GYRO_LOW_PASS_2_62,
}
d.Configure(config)
// Read the accelation, rotation and temperature data and print them.
for {
acc_x, acc_y, acc_z := d.ReadAcceleration()
gyro_x, gyro_y, gyro_z := d.ReadRotation()
temp, _ := d.ReadTemperature()
println("-------------------------------")
println("acc:", acc_x, acc_y, acc_z)
println("gyro:", gyro_x, gyro_y, gyro_z)
println("temp:", temp)
time.Sleep(time.Millisecond * 100)
}
}
+16 -16
View File
@@ -7,16 +7,15 @@
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
// go get -u github.com/eclipse/paho.mqtt.golang
//
// You can check that mqttpub is running successfully with the following command.
//
// mosquitto_sub -h test.mosquitto.org -t tinygo
// mosquitto_sub -h test.mosquitto.org -t tinygo
//
package main
import (
"machine"
"fmt"
"math/rand"
"time"
@@ -29,23 +28,23 @@ import (
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// debug = true
// server = "tinygo.org"
// }
var (
ssid string
pass string
server string = "tcp://test.mosquitto.org:1883"
debug = false
ssid string
password string
server string = "tcp://test.mosquitto.org:1883"
debug = false
)
var buf [0x400]byte
var lastRequestTime time.Time
var conn net.Conn
var adaptor *rtl8720dn.Driver
var adaptor *rtl8720dn.RTL8720DN
func main() {
err := run()
@@ -60,17 +59,18 @@ var (
)
func run() error {
// change the UART and pins as needed for platforms other than the WioTerminal.
adaptor = rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -0,0 +1,74 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
if debug {
waitSerial()
}
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+17 -17
View File
@@ -7,17 +7,16 @@
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
// go get -u github.com/eclipse/paho.mqtt.golang
//
// You can check that mqttpub/mqttsub is running successfully with the following command.
//
// mosquitto_sub -h test.mosquitto.org -t tinygo/tx
// mosquitto_pub -h test.mosquitto.org -t tinygo/rx -m "hello world"
// mosquitto_sub -h test.mosquitto.org -t tinygo/tx
// mosquitto_pub -h test.mosquitto.org -t tinygo/rx -m "hello world"
//
package main
import (
"machine"
"fmt"
"math/rand"
"time"
@@ -30,23 +29,23 @@ import (
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// debug = true
// server = "tinygo.org"
// }
var (
ssid string
pass string
server string = "tcp://test.mosquitto.org:1883"
debug = false
ssid string
password string
server string = "tcp://test.mosquitto.org:1883"
debug = false
)
var buf [0x400]byte
var lastRequestTime time.Time
var conn net.Conn
var adaptor *rtl8720dn.Driver
var adaptor *rtl8720dn.RTL8720DN
func main() {
err := run()
@@ -69,17 +68,18 @@ func subHandler(client mqtt.Client, msg mqtt.Message) {
}
func run() error {
// change the UART and pins as needed for platforms other than the WioTerminal.
adaptor = rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
+74
View File
@@ -0,0 +1,74 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
if debug {
waitSerial()
}
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+15 -14
View File
@@ -4,31 +4,28 @@
package main
import (
"machine"
"errors"
"fmt"
"runtime"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/rtl8720dn"
)
// IP address of the server aka "hub". Replace with your own info.
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// ntpHost = "129.6.15.29"
// debug = true
// }
var (
ssid string
pass string
ntpHost = "129.6.15.29"
debug = false
ssid string
password string
ntpHost = "129.6.15.29"
debug = false
)
const NTP_PACKET_SIZE = 48
@@ -44,16 +41,18 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -100,7 +99,9 @@ func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
}
return parseNTPpacket(), nil
}
@@ -0,0 +1,72 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
waitSerial()
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+11 -11
View File
@@ -4,30 +4,28 @@
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
//
package main
import (
"machine"
"bytes"
"fmt"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// ssid = "sghome-gw"
// password = "3af25537b4524"
// serverIP = "192.168.1.119"
// debug = true
// }
var (
ssid string
pass string
password string
serverIP = ""
debug = false
)
@@ -43,16 +41,18 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -0,0 +1,72 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
waitSerial()
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+14 -14
View File
@@ -1,8 +1,6 @@
package main
import (
"machine"
"bufio"
"fmt"
"strings"
@@ -16,17 +14,17 @@ import (
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// debug = true
// url = "https://www.example.com"
// test_root_ca = "..."
// }
var (
ssid string
pass string
url string = "https://www.example.com"
debug = false
ssid string
password string
url string = "https://www.example.com"
debug = false
)
// Set the test_root_ca created by the following command
@@ -59,6 +57,7 @@ var buf [0x1000]byte
var lastRequestTime time.Time
var conn net.Conn
var adaptor *rtl8720dn.RTL8720DN
func main() {
err := run()
@@ -69,19 +68,20 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
adaptor.SetRootCA(&test_root_ca)
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
rtl.SetRootCA(&test_root_ca)
net.UseDriver(rtl)
http.SetBuf(buf[:])
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -0,0 +1,72 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
waitSerial()
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+12 -14
View File
@@ -1,31 +1,28 @@
package main
import (
"machine"
"fmt"
"strconv"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
)
// IP address of the server aka "hub". Replace with your own info.
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// hubIP = "192.168.1.118"
// debug = true
// }
var (
ssid string
pass string
hubIP = ""
debug = false
ssid string
password string
hubIP = ""
debug = false
)
var buf [0x400]byte
@@ -39,18 +36,19 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
http.SetBuf(buf[:])
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -0,0 +1,72 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
waitSerial()
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+7 -7
View File
@@ -1,12 +1,10 @@
package main
import (
"machine"
"fmt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
"tinygo.org/x/drivers/examples/rtl8720dn"
)
var (
@@ -22,11 +20,13 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
//rtl8720dn.Debug(true)
rtl, err := rtl8720dn.Setup()
if err != nil {
return err
}
ver, err := adaptor.Version()
ver, err := rtl.Version()
if err != nil {
return nil
}
+13 -39
View File
@@ -1,18 +1,14 @@
package main
import (
"machine"
"bufio"
"fmt"
"image/color"
"strings"
"time"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
"tinygo.org/x/tinyfont/proggy"
"tinygo.org/x/tinyterm"
)
@@ -21,28 +17,19 @@ import (
// If debug is enabled, a serial connection is required.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// debug = false // true
// server = "tinygo.org"
// }
var (
ssid string
pass string
url = "http://tinygo.org/"
debug = false
ssid string
password string
url = "http://tinygo.org/"
debug = false
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
terminal = tinyterm.NewTerminal(display)
black = color.RGBA{0, 0, 0, 255}
@@ -79,22 +66,21 @@ func run() error {
fmt.Fprintf(terminal, "Running in debug mode.\r\n")
fmt.Fprintf(terminal, "A serial connection is required to continue execution.\r\n")
}
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
http.UseDriver(adaptor)
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
http.SetBuf(buf[:])
fmt.Fprintf(terminal, "ConnectToAP()\r\n")
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
fmt.Fprintf(terminal, "connected\r\n\r\n")
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -148,15 +134,3 @@ func run() error {
time.Sleep(10 * time.Second)
}
}
func init() {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
display.Configure(ili9341.Config{})
backlight.Configure(machine.PinConfig{machine.PinOutput})
}
@@ -0,0 +1,98 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
)
func init() {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
display.Configure(ili9341.Config{})
backlight.Configure(machine.PinConfig{machine.PinOutput})
}
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
if debug {
waitSerial()
}
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+13 -15
View File
@@ -1,30 +1,28 @@
package main
import (
"machine"
"bufio"
"fmt"
"strings"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// url = "http://tinygo.org/"
// debug = true
// }
var (
ssid string
pass string
url = "http://tinygo.org/"
debug = false
ssid string
password string
url = "http://tinygo.org/"
debug = false
)
var buf [0x400]byte
@@ -38,19 +36,19 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
http.UseDriver(adaptor)
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
net.UseDriver(rtl)
http.SetBuf(buf[:])
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -0,0 +1,72 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
waitSerial()
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+11 -12
View File
@@ -7,20 +7,19 @@ import (
"time"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// password = "your-password"
// debug = true
// }
var (
ssid string
pass string
debug = false
ssid string
password string
debug = false
)
var led = machine.LED
@@ -38,18 +37,18 @@ func main() {
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
rtl, err := setupRTL8720DN()
if err != nil {
return err
}
http.UseDriver(rtl)
http.UseDriver(adaptor)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
ip, subnet, gateway, err := adaptor.GetIP()
ip, subnet, gateway, err := rtl.GetIP()
if err != nil {
return err
}
@@ -0,0 +1,74 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
if debug {
waitSerial()
}
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init()
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
+79
View File
@@ -0,0 +1,79 @@
//go:build wioterminal
// +build wioterminal
package rtl8720dn
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
uart UARTx
debug bool
)
func handleInterrupt(interrupt.Interrupt) {
// should reset IRQ
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
}
func Setup() (*rtl8720dn.RTL8720DN, error) {
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RTL8720D_CHIP_PU.Low()
time.Sleep(100 * time.Millisecond)
machine.RTL8720D_CHIP_PU.High()
time.Sleep(1000 * time.Millisecond)
if debug {
waitSerial()
}
uart = UARTx{
UART: &machine.UART{
Buffer: machine.NewRingBuffer(),
Bus: sam.SERCOM0_USART_INT,
SERCOM: 0,
},
}
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
rtl := rtl8720dn.New(uart)
rtl.Debug(debug)
_, err := rtl.Rpc_tcpip_adapter_init_with_timeout(10 * time.Second)
if err != nil {
return nil, err
}
return rtl, nil
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
type UARTx struct {
*machine.UART
}
func (u UARTx) Read(p []byte) (n int, err error) {
if u.Buffered() == 0 {
time.Sleep(1 * time.Millisecond)
return 0, nil
}
return u.UART.Read(p)
}
func Debug(b bool) {
debug = b
}

Some files were not shown because too many files have changed in this diff Show More