Compare commits

...

45 Commits

Author SHA1 Message Date
deadprogram 26aa664c80 espat: add Debug field to driver, and the associated behavior you would expect
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-02-03 19:56:27 +01:00
deadprogram 2d644c8b60 espat: some improvements for response handling
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-02-02 12:20:16 +01:00
deadprogram f7dce6ae22 wifinina: correct sendParamStr to handle empty strings, such as when connecting to an unsecured access point.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-26 23:05:50 +01:00
deadprogram a15f2167cc release: prepare for v0.19.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-26 18:26:16 +01:00
deadprogram 5d5378a47c all: update license year to 2022
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-26 18:25:15 +01:00
deadprogram 3ceb688663 examples/wifi: add unified example for tcpclient that compiles for all supported wifi adaptors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-24 13:24:39 +01:00
deadprogram 941c1c9057 wifi/espat, rtl8720dn, wifinina, net: modify to use Adapter interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-24 13:24:39 +01:00
deadprogram d8c813d515 wifi/espat, rtl8720dn, wifinina: move towards standard common interface for wifi adaptors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-24 13:24:39 +01:00
Drayton Munster 905fc6fce3 hd44780: fix 4-bit data length flag 2022-01-20 20:01:37 +01:00
Drayton Munster 80913d5fe7 Reset data pins to output mode after reading 2022-01-20 20:01:37 +01:00
Olivier Fauchon b6c750ccd1 sx126x: Driver for Semtech sx126x radio modules and optional RF Switch.
This first version of the driver has been tested with STM32WL SoC,
	which embeddeds SX1262 radio on the same die.
2022-01-15 17:22:36 +01:00
deadprogram 43899e1330 build: remove smoketest for Arduino keyboard4x4 for now
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-12 18:26:10 +01:00
sago35 45c68ef0fc ft6336: add support for ft6336 2022-01-04 15:54:35 +01:00
Olivier Fauchon 025a66655f shtc3: Sensirion SHTC3 Relative Humidity / Temperature i2c sensor 2021-12-28 16:02:10 +01:00
deadprogram 121e8147f7 hd44780i2c: clean up for go fmt
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-24 16:00:39 +01:00
Alan Wang b48bc5ac5d Update hd44780i2c.go 2021-12-24 11:54:00 +01:00
Alan Wang 0d40c99d1f Add files via upload 2021-12-22 16:49:54 +01:00
Alan Wang bee7422c3a Fix Nano 33 BLE drivers (#351)
Fix HTS221, LPS22HB and APDS9960 drivers and their examples for Arduino Nano 33 BLE:

* Update hts221_nano_33_ble.go
* Update lps22hb_nano_33_ble.go
* Update apds9960_nano_33_ble.go
2021-12-20 09:57:37 +01:00
spearson78 43099c5d5f XPT2046 Touch driver (#350)
Co-authored-by: Steven Pearson <steven.pearson.78@gmail.com>
2021-12-14 09:14:10 +09:00
Yurii Soldak 0f9b9d873b wifinina: avoid busy wait 2021-12-10 12:15:56 +01:00
sago35 114e24870e ili9341, ili9342: add support for m5stack 2021-11-27 13:03:07 +01:00
soypat b33c84ff78 add PCA9685 driver 2021-11-21 14:46:15 +01:00
sago35 966210f1b0 ili9341, ili9342: add support for m5stack-core2 2021-11-20 12:20:34 +01:00
deadprogram 90a13a697b release: prepare for v0.18.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-18 15:25:24 +01:00
deadprogram d632eb888f docs: add LSM9DS1 to list
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-18 11:39:27 +01:00
Yurii Soldak f6761a9079 lsm9ds1: minimal implementation 2021-11-18 11:36:16 +01:00
sago35 51c3aa271b axp192: add support for AXP192 single Cell Li-Battery and power system management IC 2021-11-18 11:18:30 +01:00
soypat 520234e9f8 mcp3008: fix bitshift bug 2021-11-14 18:10:48 +01:00
Yurii Soldak 334ed57373 wifinina: control nina pins, for example leds 2021-11-12 15:32:21 +01:00
Sam Lader 3637033fec Fix broken link for SHT3x datasheet (#327)
docs: fix broken link for SHT3x datasheet
2021-11-06 21:26:08 +01:00
deadprogram 233866443c docs: update list of supported drivers with recent additions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-06 18:34:08 +01:00
Alan Wang 65fd7aa1a1 Add support for APDS-9960, Digital Proximity, Ambient Light, RGB and Gesture Sensor (#308)
apds9960: add support for apds9960
2021-11-06 11:22:39 +01:00
Alan Wang 82e9e4a7f3 Add support for LPS22HB MEMS nano pressure sensor (#297)
lps22hb: add support for lps22hb
2021-11-06 11:14:21 +01:00
deadprogram 76ff632134 hts221: update build tags for Go 1.17+
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-06 11:05:25 +01:00
Alan Wang cd2694e85f Add support for HTS221 capacitive digital sensor for relative humidity and temperature (#295)
hts221: Add support for hts221.go
2021-11-06 11:02:30 +01:00
sago35 734adb6df8 i2csoft: fix Configure() 2021-11-04 15:02:21 +01:00
sago35 2492fcb322 i2csoft: gofmt 2021-11-04 15:02:21 +01:00
sago35 4f82c231cb i2csoft: add source code for each target 2021-11-04 15:02:21 +01:00
sago35 2c9a05a413 i2csoft: remove the return value 2021-11-04 15:02:21 +01:00
sago35 a89a26112e i2csoft: fix baudrate handling 2021-11-04 15:02:21 +01:00
sago35 bd42656644 i2csoft: add support for software I2C 2021-11-04 15:02:21 +01:00
Ayke van Laethem 94729a4f7d ws2812: add support for RISC-V
This commit adds support for two new chips using the RISC-V
architecture: the FE310 (used in the HiFive 1) and the ESP32-C3 from
Espressif.
2021-11-03 19:14:32 +01:00
Ayke van Laethem 050cf4dbbc ws2812: make assembly generator architecture independent 2021-11-03 19:14:32 +01:00
sago35 49c8810432 ili9341: refactor examples/ili9341 2021-10-31 20:12:50 +01:00
Yurii Soldak 4b38841f71 net: fix raddr of tcp conn 2021-10-26 11:22:45 +02:00
139 changed files with 7723 additions and 678 deletions
+58
View File
@@ -1,3 +1,61 @@
0.19.0
---
- **new devices**
- ft6336: add support for ft6336
- pca9685: PCA9685 driver
- shtc3: Sensirion SHTC3 Relative Humidity / Temperature i2c sensor
- sx126x: Driver for Semtech sx126x radio modules
- xpt2046: XPT2046 Touch driver (#350)
- **enhancements**
- **hd44780i2c**
- clean up for go fmt
- Needed fixes and update hd44780i2c.go
- **ili9341, ili9342**
- add support for m5stack
- add support for m5stack-core2
- **wifi**
- modify to use shared net.Adapter interface for all supported wifi devices
- wifinina: remove busy wait
- **bugfixes**
- **hd44780**
- fix 4-bit data length flag
- Reset data pins to output mode after reading
- Nano 33 BLE drivers (#351)
- **docs**
- examples/wifi: add unified example for tcpclient that compiles for all supported wifi adaptors
0.18.0
---
- **new devices**
- apds9960: add support for APDS-9960 Digital Proximity sensor
- axp192: add support for AXP192 single Cell Li-Battery and power system management IC
- hts221: add support for HTS221 capacitive digital sensor for relative humidity and temperature
- i2csoft: add support for software I2C
- image: add support for image/jpeg and image/png
- lps22hb: add support for LPS22HB MEMS nano pressure sensor
- lsm6dox: add support for lsm6dox accelerometer
- lsm9ds1: add support for lsm9ds1 accelerometer
- **enhancements**
- ili9341: change to use drivers.SPI interface
- **ws2812**
- generate assembly instead of handwriting it
- improve timings to be compatible with the WS2811
- add support for 168MHz (e.g. Adafruit Feather STM32F405)
- add support for RISC-V
- wifinina: control nina pins, for example leds
- **docs**
- rtl8720dn: examples for tcpclient, udpstation, mqtt, and webserver
- **wifinina**
- nina-fw update docs
- examples/wifinina/http-get
- ili9341: refactor examples
- Fix broken link for SHT3x datasheet
- **core**
- all: use build directives for both Go1.17 and earlier versions
- **bugfixes**
- net: fix raddr of tcp conn
- mcp3008: fix bitshift bug
0.17.1
---
- To correct an error in the release process. Same as 0.17.0.
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018-2021 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
+24 -3
View File
@@ -17,6 +17,8 @@ smoke-test:
@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
@@ -63,6 +65,8 @@ smoke-test:
@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
@@ -79,6 +83,8 @@ smoke-test:
@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
@@ -111,6 +117,8 @@ smoke-test:
@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
@@ -181,8 +189,8 @@ endif
@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=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/
@@ -205,12 +213,25 @@ endif
@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
DRIVERS = $(wildcard */)
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192 xpt2046 \
ft6336 sx126x
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
unit-test:
+16 -4
View File
@@ -52,7 +52,7 @@ func main() {
## Currently supported devices
The following 67 devices are supported.
The following 78 devices are supported.
| Device Name | Interface Type |
|----------|-------------|
@@ -61,7 +61,9 @@ The following 67 devices are supported.
| [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 |
@@ -76,10 +78,13 @@ The following 67 devices are supported.
| [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 |
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
@@ -87,12 +92,16 @@ The following 67 devices are supported.
| [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 |
| [LSM303AGR accelerometer](https://www.st.com/resource/en/datasheet/lsm303agr.pdf) | I2C |
| [LSM9DS1 accelerometer](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) | I2C |
| [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 |
| [MCP23017 port expander](https://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf) | I2C |
| [MCP3008 analog to digital converter (ADC)](http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.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 |
@@ -105,7 +114,8 @@ The following 67 devices are supported.
| [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/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
| [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 |
@@ -123,6 +133,8 @@ The following 67 devices are supported.
| [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 |
## Contributing
+468
View File
@@ -0,0 +1,468 @@
// Package apds9960 implements a driver for APDS-9960,
// 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 (
"time"
"tinygo.org/x/drivers"
)
// Device wraps an I2C connection to a APDS-9960 device.
type Device struct {
bus drivers.I2C
Address uint8
mode uint8
gesture gestureData
}
// Configuration for APDS-9960 device.
type Configuration struct {
ProximityPulseLength uint8
ProximityPulseCount uint8
GesturePulseLength uint8
GesturePulseCount uint8
ProximityGain uint8
GestureGain uint8
ColorGain uint8
ADCIntegrationCycles uint16
LEDBoost uint16
threshold uint8
sensitivity uint8
}
// for gesture-related data
type gestureData struct {
detected uint8
threshold uint8
sensitivity uint8
gXDelta int16
gYDelta int16
gXPrevDelta int16
gYPrevDelta int16
received bool
}
// for enabling various device function
type enableConfig struct {
GEN bool
PIEN bool
AIEN bool
WEN bool
PEN bool
AEN bool
PON bool
}
// New creates a new APDS-9960 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus drivers.I2C) Device {
return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE}
}
// Connected returns whether APDS-9960 has been found.
// It does a "who am I" request and checks the response.
func (d *Device) Connected() bool {
data := []byte{0}
d.bus.ReadRegister(d.Address, APDS9960_ID_REG, data)
return data[0] == 0xAB
}
// GetMode returns current engine mode
func (d *Device) GetMode() uint8 {
return d.mode
}
// DisableAll turns off the device and all functions
func (d *Device) DisableAll() {
d.enable(enableConfig{})
d.bus.WriteRegister(d.Address, APDS9960_GCONF4_REG, []byte{0x00})
d.mode = MODE_NONE
d.gesture.detected = GESTURE_NONE
}
// SetProximityPulse sets proximity pulse length (4, 8, 16, 32) and count (1~64)
// default: 16, 64
func (d *Device) SetProximityPulse(length, count uint8) {
d.bus.WriteRegister(d.Address, APDS9960_PPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)})
}
// SetGesturePulse sets gesture pulse length (4, 8, 16, 32) and count (1~64)
// default: 16, 64
func (d *Device) SetGesturePulse(length, count uint8) {
d.bus.WriteRegister(d.Address, APDS9960_GPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)})
}
// SetADCIntegrationCycles sets ALS/color ADC internal integration cycles (1~256, 1 cycle = 2.78 ms)
// default: 4 (~10 ms)
func (d *Device) SetADCIntegrationCycles(cycles uint16) {
if cycles > 256 {
cycles = 256
}
d.bus.WriteRegister(d.Address, APDS9960_ATIME_REG, []byte{uint8(256 - cycles)})
}
// SetGains sets proximity/gesture gain (1, 2, 4, 8x) and ALS/color gain (1, 4, 16, 64x)
// default: 1, 1, 4
func (d *Device) SetGains(proximityGain, gestureGain, colorGain uint8) {
d.bus.WriteRegister(d.Address, APDS9960_CONTROL_REG, []byte{getProximityGain(proximityGain)<<2 | getALSGain(colorGain)})
d.bus.WriteRegister(d.Address, APDS9960_GCONF2_REG, []byte{getProximityGain(gestureGain) << 5})
}
// LEDBoost sets proximity and gesture LED current level (100, 150, 200, 300 (%))
// default: 100
func (d *Device) LEDBoost(percent uint16) {
var v uint8
switch percent {
case 100:
v = 0
case 150:
v = 1
case 200:
v = 2
case 300:
v = 3
}
d.bus.WriteRegister(d.Address, APDS9960_CONFIG2_REG, []byte{0x01 | v<<4})
}
// Setthreshold sets threshold (0~255) for detecting gestures
// default: 30
func (d *Device) Setthreshold(t uint8) {
d.gesture.threshold = t
}
// Setsensitivity sets sensivity (0~100) for detecting gestures
// default: 20
func (d *Device) Setsensitivity(s uint8) {
if s > 100 {
s = 100
}
d.gesture.sensitivity = 100 - s
}
// EnableProximity starts the proximity engine
func (d *Device) EnableProximity() {
if d.mode != MODE_NONE {
d.DisableAll()
}
d.enable(enableConfig{PON: true, PEN: true, WEN: true})
d.mode = MODE_PROXIMITY
}
// ProximityAvailable reports if proximity data is available
func (d *Device) ProximityAvailable() bool {
if d.mode == MODE_PROXIMITY && d.readStatus("PVALID") {
return true
}
return false
}
// ReadProximity reads proximity data (0~255)
func (d *Device) ReadProximity() (proximity int32) {
if d.mode != MODE_PROXIMITY {
return 0
}
data := []byte{0}
d.bus.ReadRegister(d.Address, APDS9960_PDATA_REG, data)
return 255 - int32(data[0])
}
// EnableColor starts the color engine
func (d *Device) EnableColor() {
if d.mode != MODE_NONE {
d.DisableAll()
}
d.enable(enableConfig{PON: true, AEN: true, WEN: true})
d.mode = MODE_COLOR
}
// ColorAvailable reports if color data is available
func (d *Device) ColorAvailable() bool {
if d.mode == MODE_COLOR && d.readStatus("AVALID") {
return true
}
return false
}
// ReadColor reads color data (red, green, blue, clear color/brightness)
func (d *Device) ReadColor() (r int32, g int32, b int32, clear int32) {
if d.mode != MODE_COLOR {
return
}
data := []byte{0, 0, 0, 0, 0, 0, 0, 0}
d.bus.ReadRegister(d.Address, APDS9960_CDATAL_REG, data[:1])
d.bus.ReadRegister(d.Address, APDS9960_CDATAH_REG, data[1:2])
d.bus.ReadRegister(d.Address, APDS9960_RDATAL_REG, data[2:3])
d.bus.ReadRegister(d.Address, APDS9960_RDATAH_REG, data[3:4])
d.bus.ReadRegister(d.Address, APDS9960_GDATAL_REG, data[4:5])
d.bus.ReadRegister(d.Address, APDS9960_GDATAH_REG, data[5:6])
d.bus.ReadRegister(d.Address, APDS9960_BDATAL_REG, data[6:7])
d.bus.ReadRegister(d.Address, APDS9960_BDATAH_REG, data[7:])
clear = int32(uint16(data[1])<<8 | uint16(data[0]))
r = int32(uint16(data[3])<<8 | uint16(data[2]))
g = int32(uint16(data[5])<<8 | uint16(data[4]))
b = int32(uint16(data[7])<<8 | uint16(data[6]))
return
}
// EnableGesture starts the gesture engine
func (d *Device) EnableGesture() {
if d.mode != MODE_NONE {
d.DisableAll()
}
d.enable(enableConfig{PON: true, PEN: true, GEN: true, WEN: true})
d.mode = MODE_GESTURE
d.gesture.detected = GESTURE_NONE
d.gesture.gXDelta = 0
d.gesture.gYDelta = 0
d.gesture.gXPrevDelta = 0
d.gesture.gYPrevDelta = 0
d.gesture.received = false
}
// GestureAvailable reports if gesture data is available
func (d *Device) GestureAvailable() bool {
if d.mode != MODE_GESTURE {
return false
}
data := []byte{0, 0, 0, 0}
// check GVALID
d.bus.ReadRegister(d.Address, APDS9960_GSTATUS_REG, data[:1])
if data[0]&0x01 == 0 {
return false
}
// get number of data sets available in FIFO
d.bus.ReadRegister(d.Address, APDS9960_GFLVL_REG, data[:1])
availableDataSets := data[0]
if availableDataSets == 0 {
return false
}
// read up, down, left and right proximity data from FIFO
var dataSets [32][4]uint8
for i := uint8(0); i < availableDataSets; i++ {
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_U_REG, data[:1])
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_D_REG, data[1:2])
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_L_REG, data[2:3])
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_R_REG, data[3:4])
for j := uint8(0); j < 4; j++ {
dataSets[i][j] = data[j]
}
}
// gesture detection process
d.gesture.detected = GESTURE_NONE
for i := uint8(0); i < availableDataSets; i++ {
U := dataSets[i][0]
D := dataSets[i][1]
L := dataSets[i][2]
R := dataSets[i][3]
// if all readings fall below threshold, it's possible that
// a movement's just been made
if U < d.gesture.threshold && D < d.gesture.threshold && L < d.gesture.threshold && R < d.gesture.threshold {
d.gesture.received = true
// if there were movement in the previous step (including the last data sets)
if d.gesture.gXPrevDelta != 0 && d.gesture.gYPrevDelta != 0 {
totalX := d.gesture.gXPrevDelta - d.gesture.gXDelta
totalY := d.gesture.gYPrevDelta - d.gesture.gYDelta
// if previous and current movement are in opposite directions (pass through one led then next)
// and the difference is big enough, the gesture is recorded
switch {
case totalX < -int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_LEFT
case totalX > int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_RIGHT
case totalY > int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_DOWN
case totalY < -int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_UP
}
d.gesture.gXDelta = 0
d.gesture.gYDelta = 0
d.gesture.gXPrevDelta = 0
d.gesture.gYPrevDelta = 0
}
continue
}
// recording current movement
d.gesture.gXDelta = int16(R) - int16(L)
d.gesture.gYDelta = int16(D) - int16(U)
if d.gesture.received {
d.gesture.received = false
d.gesture.gXPrevDelta = d.gesture.gXDelta
d.gesture.gYPrevDelta = d.gesture.gYDelta
}
}
return d.gesture.detected != GESTURE_NONE
}
// ReadGesture reads last gesture data
func (d *Device) ReadGesture() (gesture int32) {
return int32(d.gesture.detected)
}
// private functions
func (d *Device) configureDevice(cfg Configuration) {
d.DisableAll() // turn off everything
// "default" settings
if cfg.ProximityPulseLength == 0 {
cfg.ProximityPulseLength = 16
}
if cfg.ProximityPulseCount == 0 {
cfg.ProximityPulseCount = 64
}
if cfg.GesturePulseLength == 0 {
cfg.GesturePulseLength = 16
}
if cfg.GesturePulseCount == 0 {
cfg.GesturePulseCount = 64
}
if cfg.ProximityGain == 0 {
cfg.ProximityGain = 1
}
if cfg.GestureGain == 0 {
cfg.GestureGain = 1
}
if cfg.ColorGain == 0 {
cfg.ColorGain = 4
}
if cfg.ADCIntegrationCycles == 0 {
cfg.ADCIntegrationCycles = 4
}
if cfg.threshold == 0 {
d.gesture.threshold = 30
}
if cfg.sensitivity == 0 {
d.gesture.sensitivity = 20
}
d.SetProximityPulse(cfg.ProximityPulseLength, cfg.ProximityPulseCount)
d.SetGesturePulse(cfg.GesturePulseLength, cfg.GesturePulseCount)
d.SetGains(cfg.ProximityGain, cfg.GestureGain, cfg.ColorGain)
d.SetADCIntegrationCycles(cfg.ADCIntegrationCycles)
if cfg.LEDBoost > 0 {
d.LEDBoost(cfg.LEDBoost)
}
}
func (d *Device) enable(cfg enableConfig) {
var gen, pien, aien, wen, pen, aen, pon uint8
if cfg.GEN {
gen = 1
}
if cfg.PIEN {
pien = 1
}
if cfg.AIEN {
aien = 1
}
if cfg.WEN {
wen = 1
}
if cfg.PEN {
pen = 1
}
if cfg.AEN {
aen = 1
}
if cfg.PON {
pon = 1
}
data := []byte{gen<<6 | pien<<5 | aien<<4 | wen<<3 | pen<<2 | aen<<1 | pon}
d.bus.WriteRegister(d.Address, APDS9960_ENABLE_REG, data)
if cfg.PON {
time.Sleep(time.Millisecond * 10)
}
}
func (d *Device) readStatus(param string) bool {
data := []byte{0}
d.bus.ReadRegister(d.Address, APDS9960_STATUS_REG, data)
switch param {
case "CPSAT":
return data[0]>>7&0x01 == 1
case "PGSAT":
return data[0]>>6&0x01 == 1
case "PINT":
return data[0]>>5&0x01 == 1
case "AINT":
return data[0]>>4&0x01 == 1
case "PVALID":
return data[0]>>1&0x01 == 1
case "AVALID":
return data[0]&0x01 == 1
default:
return false
}
}
func getPulseLength(l uint8) uint8 {
switch l {
case 4:
return 0
case 8:
return 1
case 16:
return 2
case 32:
return 3
default:
return 0
}
}
func getPulseCount(c uint8) uint8 {
if c < 1 && c > 64 {
return 0
}
return c - 1
}
func getProximityGain(g uint8) uint8 {
switch g {
case 1:
return 0
case 2:
return 1
case 4:
return 2
case 8:
return 3
default:
return 0
}
}
func getALSGain(g uint8) uint8 {
switch g {
case 1:
return 0
case 4:
return 1
case 16:
return 2
case 64:
return 3
default:
return 0
}
}
+12
View File
@@ -0,0 +1,12 @@
//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
d.configureDevice(cfg)
}
+24
View File
@@ -0,0 +1,24 @@
//go:build nano_33_ble
// +build nano_33_ble
package apds9960
import (
"machine"
"time"
)
// Configure sets up the APDS-9960 device.
func (d *Device) Configure(cfg Configuration) {
// Following lines are Nano 33 BLE specific, they have nothing to do with sensor per se
machine.LSM_PWR.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LSM_PWR.High()
machine.I2C_PULLUP.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.I2C_PULLUP.High()
// Wait a moment
time.Sleep(10 * time.Millisecond)
// configure device
d.configureDevice(cfg)
}
+78
View File
@@ -0,0 +1,78 @@
package apds9960
const (
// I2C address
ADPS9960_ADDRESS = 0x39
// control/status registers
APDS9960_RAM_REG = 0x00
APDS9960_ENABLE_REG = 0x80
APDS9960_ATIME_REG = 0x81
APDS9960_WTIME_REG = 0x83
APDS9960_AILTIL_REG = 0x84
APDS9960_AILTH_REG = 0x85
APDS9960_AIHTL_REG = 0x86
APDS9960_AIHTH_REG = 0x87
APDS9960_PILT_REG = 0x89
APDS9960_PIHT_REG = 0x8B
APDS9960_PERS_REG = 0x8C
APDS9960_CONFIG1_REG = 0x8D
APDS9960_PPULSE_REG = 0x8E
APDS9960_CONTROL_REG = 0x8F
APDS9960_CONFIG2_REG = 0x90
APDS9960_ID_REG = 0x92
APDS9960_STATUS_REG = 0x93
APDS9960_CDATAL_REG = 0x94
APDS9960_CDATAH_REG = 0x95
APDS9960_RDATAL_REG = 0x96
APDS9960_RDATAH_REG = 0x97
APDS9960_GDATAL_REG = 0x98
APDS9960_GDATAH_REG = 0x99
APDS9960_BDATAL_REG = 0x9A
APDS9960_BDATAH_REG = 0x9B
APDS9960_PDATA_REG = 0x9C
APDS9960_POFFSET_UR_REG = 0x9D
APDS9960_POFFSET_DL_REG = 0x9E
APDS9960_CONFIG3_REG = 0x9F
APDS9960_GPENTH_REG = 0xA0
APDS9960_GEXTH_REG = 0xA1
APDS9960_GCONF1_REG = 0xA2
APDS9960_GCONF2_REG = 0xA3
APDS9960_GOFFSET_U_REG = 0xA4
APDS9960_GOFFSET_D_REG = 0xA5
APDS9960_GOFFSET_L_REG = 0xA7
APDS9960_GOFFSET_R_REG = 0xA9
APDS9960_GPULSE_REG = 0xA6
APDS9960_GCONF3_REG = 0xAA
APDS9960_GCONF4_REG = 0xAB
APDS9960_GFLVL_REG = 0xAE
APDS9960_GSTATUS_REG = 0xAF
APDS9960_IFORCE_REG = 0xE4
APDS9960_PICLEAR_REG = 0xE5
APDS9960_CICLEAR_REG = 0xE6
APDS9960_AICLEAR_REG = 0xE7
APDS9960_GFIFO_U_REG = 0xFC
APDS9960_GFIFO_D_REG = 0xFD
APDS9960_GFIFO_L_REG = 0xFE
APDS9960_GFIFO_R_REG = 0xFF
)
const (
// sensor modes
MODE_NONE = iota
MODE_PROXIMITY
MODE_COLOR
MODE_GESTURE
)
const (
// detected gestures
GESTURE_NONE = iota
GESTURE_UP
GESTURE_DOWN
GESTURE_LEFT
GESTURE_RIGHT
)
+258
View File
@@ -0,0 +1,258 @@
// Package axp192 provides a driver for the axp192 I2C Enhanced single Cell
// Li-Battery and Power System Management IC.
//
// 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 (
"tinygo.org/x/drivers"
)
type Error uint8
const (
ErrInvalidID Error = 0x1
)
func (e Error) Error() string {
switch e {
case ErrInvalidID:
return "Invalid chip ID"
default:
return "Unknown error"
}
}
type Device struct {
bus drivers.I2C
buf []byte
Address uint8
}
// New returns AXP192 device for the provided I2C bus using default address.
func New(i2c drivers.I2C) *Device {
return &Device{
bus: i2c,
buf: make([]byte, 2),
Address: Address,
}
}
type Config struct {
}
// Configure the AXP192 device.
func (d *Device) Configure(config Config) error {
return nil
}
// ReadPowerSupplyStatus reads power supply status.
func (d *Device) ReadPowerSupplyStatus() uint8 {
return d.read8bit(RegPowerSupplyStatus)
}
// SetVbusIPSOutAccessManagement sets VBUS-IPSOUT access management.
func (d *Device) SetVbusIPSOutAccessManagement(a uint8) {
d.write1Byte(RegVbusIPSOutAccessManagement, a)
}
// GetVbusIPSOutAccessManagement gets VBUS-IPSOUT access management.
func (d *Device) GetVbusIPSOutAccessManagement() uint8 {
return d.read8bit(RegVbusIPSOutAccessManagement)
}
// SetGPIO1Control sets GPIO1 function.
func (d *Device) SetGPIO1Control(a uint8) {
d.write1Byte(RegGPIO1Control, a)
}
// GetGPIO1Control gets GPIO1 function.
func (d *Device) GetGPIO1Control() uint8 {
return d.read8bit(RegGPIO1Control)
}
// SetGPIO2Control sets GPIO2 function.
func (d *Device) SetGPIO2Control(a uint8) {
d.write1Byte(RegGPIO2Control, a)
}
// GetGPIO2Control gets GPIO2 function.
func (d *Device) GetGPIO2Control() uint8 {
return d.read8bit(RegGPIO2Control)
}
// SetGPIO20SignalStatus sets GPIO[2:0] signal status.
func (d *Device) SetGPIO20SignalStatus(a uint8) {
d.write1Byte(RegGPIO20SignalStatus, a)
}
// GetGPIO20SignalStatus gets GPIO[2:0] signal status.
func (d *Device) GetGPIO20SignalStatus() uint8 {
return d.read8bit(RegGPIO20SignalStatus)
}
// SetBackupBatteryChargingControl sets backup battery charge control.
func (d *Device) SetBackupBatteryChargingControl(a uint8) {
d.write1Byte(RegBackupBatteryChargingControl, a)
}
// GetBackupBatteryChargingControl gets backup battery charge control.
func (d *Device) GetBackupBatteryChargingControl() uint8 {
return d.read8bit(RegBackupBatteryChargingControl)
}
// SetDCDC1VoltageSet sets DC-DC1 output voltage.
func (d *Device) SetDCDC1VoltageSet(a uint8) {
d.write1Byte(RegDCDC1VoltageSet, a)
}
// GetDCDC1VoltageSet gets DC-DC1 output voltage.
func (d *Device) GetDCDC1VoltageSet() uint8 {
return d.read8bit(RegDCDC1VoltageSet)
}
// SetDCDC2VoltageSet sets DC-DC2 dynamic voltage parameter.
func (d *Device) SetDCDC2VoltageSet(a uint8) {
d.write1Byte(RegDCDC2VoltageSet, a)
}
// GetDCDC2VoltageSet gets DC-DC2 dynamic voltage parameter.
func (d *Device) GetDCDC2VoltageSet() uint8 {
return d.read8bit(RegDCDC2VoltageSet)
}
// SetDCDC3VoltageSet sets DC-DC3 output voltage.
func (d *Device) SetDCDC3VoltageSet(a uint8) {
d.write1Byte(RegDCDC3VoltageSet, a)
}
// GetDCDC3VoltageSet gets DC-DC3 output voltage.
func (d *Device) GetDCDC3VoltageSet() uint8 {
return d.read8bit(RegDCDC3VoltageSet)
}
// SetLDO23VoltageSet sets LDO2/3 output voltage.
func (d *Device) SetLDO23VoltageSet(a uint8) {
d.write1Byte(RegLDO23VoltageSet, a)
}
// GetLDO23VoltageSet gets LDO2/3 output voltage.
func (d *Device) GetLDO23VoltageSet() uint8 {
return d.read8bit(RegLDO23VoltageSet)
}
// SetDCDC13LDO23Switch sets DC-DC1/3 & LOD2/3 output control.
func (d *Device) SetDCDC13LDO23Switch(a uint8) {
d.write1Byte(RegDCDC13LDO23Switch, a)
}
// GetDCDC13LDO23Switch gets DC-DC1/3 & LOD2/3 output control.
func (d *Device) GetDCDC13LDO23Switch() uint8 {
return d.read8bit(RegDCDC13LDO23Switch)
}
// SetGPIO43FunctionControl sets GPIO[4:3] pin function.
func (d *Device) SetGPIO43FunctionControl(a uint8) {
d.write1Byte(RegGPIO43FunctionControl, a)
}
// GetGPIO43FunctionControl gets GPIO[4:3] pin function.
func (d *Device) GetGPIO43FunctionControl() uint8 {
return d.read8bit(RegGPIO43FunctionControl)
}
// SetPEKParameterSet sets PEK press key parameter.
func (d *Device) SetPEKParameterSet(a uint8) {
d.write1Byte(RegPEKParameterSet, a)
}
// GetPEKParameterSet gets PEK press key parameter.
func (d *Device) GetPEKParameterSet() uint8 {
return d.read8bit(RegPEKParameterSet)
}
// SetADCEnableSet sets ADC enable 1.
func (d *Device) SetADCEnableSet(a uint8) {
d.write1Byte(RegADCEnableSet, a)
}
// GetADCEnableSet gets ADC enable 1.
func (d *Device) GetADCEnableSet() uint8 {
return d.read8bit(RegADCEnableSet)
}
// SetGPIO43SignalStatus sets GPIO[4:3] signal status.
func (d *Device) SetGPIO43SignalStatus(a uint8) {
d.write1Byte(RegGPIO43SignalStatus, a)
}
// GetGPIO43SignalStatus gets GPIO[4:3] signal status.
func (d *Device) GetGPIO43SignalStatus() uint8 {
return d.read8bit(RegGPIO43SignalStatus)
}
// SetDCVoltage sets DC voltage.
func (d *Device) SetDCVoltage(number uint8, voltage uint16) {
if voltage < 700 {
voltage = 0
} else {
voltage = (voltage - 700) / 25
}
switch number {
case 0:
v := d.GetDCDC1VoltageSet()
d.SetDCDC1VoltageSet((v & 0x80) | (uint8(voltage) & 0x7F))
case 1:
v := d.GetDCDC2VoltageSet()
d.SetDCDC2VoltageSet((v & 0x80) | (uint8(voltage) & 0x7F))
case 2:
v := d.GetDCDC3VoltageSet()
d.SetDCDC3VoltageSet((v & 0x80) | (uint8(voltage) & 0x7F))
}
}
// SetLDOVoltage sets LDO voltage.
func (d *Device) SetLDOVoltage(number uint8, voltage uint16) {
if voltage > 3300 {
voltage = 15
} else {
voltage = (voltage / 100) - 18
}
switch number {
case 2:
v := d.GetLDO23VoltageSet()
d.SetLDO23VoltageSet((v & 0x0F) | (uint8(voltage) << 4))
break
case 3:
v := d.GetLDO23VoltageSet()
d.SetLDO23VoltageSet((v & 0xF0) | uint8(voltage))
break
}
}
// SetLDOEnable enable LDO.
func (d *Device) SetLDOEnable(number uint8, state bool) {
mark := uint8(0x01)
mark <<= number
switch number {
case 2:
v := d.GetDCDC13LDO23Switch()
d.SetDCDC13LDO23Switch(v | mark)
case 3:
v := d.GetDCDC13LDO23Switch()
d.SetDCDC13LDO23Switch(v & (^mark))
}
}
func (d *Device) write1Byte(reg, data uint8) {
d.bus.WriteRegister(d.Address, reg, []byte{data})
}
func (d *Device) read8bit(reg uint8) uint8 {
d.bus.ReadRegister(d.Address, reg, d.buf[:1])
return d.buf[0]
}
+158
View File
@@ -0,0 +1,158 @@
package axp192
import (
"time"
"tinygo.org/x/drivers"
axp192orig "tinygo.org/x/drivers/axp192"
)
// Device wraps an I2C connection to a AXP192 device.
type Device struct {
*axp192orig.Device
LED Pin
RST Pin
SPK_EN Pin
}
// New creates a new AXP192 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(i2c drivers.I2C) *Device {
d := axp192orig.New(i2c)
axp := &Device{
Device: d,
}
axp.LED = Pin{pin: 1, axp: axp}
axp.SPK_EN = Pin{pin: 2, axp: axp}
axp.RST = Pin{pin: 4, axp: axp}
axp.begin()
return axp
}
type Config struct {
}
// Configure sets up the device for communication
func (d *Device) Configure(config Config) error {
return d.Device.Configure(axp192orig.Config{})
}
func (d *Device) begin() {
d.SetVbusIPSOutAccessManagement((d.GetVbusIPSOutAccessManagement() & 0x04) | 0x02)
d.SetGPIO1Control(d.GetGPIO1Control() & 0xF8)
d.SetGPIO2Control(d.GetGPIO2Control() & 0xF8)
d.SetBackupBatteryChargingControl((d.GetBackupBatteryChargingControl() & 0x1C) | 0xA2)
d.SetESPVoltage(3350)
d.SetLcdVoltage(3300)
d.SetLDOVoltage(2, 3300) //Periph power voltage preset (LCD_logic, SD card)
d.SetLDOVoltage(3, 2000) //Vibrator power voltage preset
d.SetLDOEnable(2, true)
d.SetDCDC3(true) // LCD Backlight
// GPIO4 : LCD Reset
d.SetGPIO43FunctionControl((d.GetGPIO43FunctionControl() & 0x72) | 0x84)
// Power On/Off Setting
d.SetPEKParameterSet(0x4C)
d.SetADCEnableSet(0xFF)
d.RST.Low()
time.Sleep(100 * time.Millisecond)
d.RST.High()
time.Sleep(100 * time.Millisecond)
}
// ToggleLED toggles LED connected to AXP192.
func (d *Device) ToggleLED() {
v := d.GetGPIO20SignalStatus()
if (v & 0x02) > 0 {
d.SetGPIO20SignalStatus(v & 0xFD)
} else {
d.SetGPIO20SignalStatus(v | 0x02)
}
}
// SetESPVoltage sets voltage of ESP32.
func (d *Device) SetESPVoltage(voltage uint16) {
if voltage >= 3000 && voltage <= 3400 {
d.SetDCVoltage(0, voltage)
}
}
// SetLcdVoltage sets voltage of LCD.
func (d *Device) SetLcdVoltage(voltage uint16) {
if voltage >= 2500 && voltage <= 3300 {
d.SetDCVoltage(2, voltage)
}
}
// SetDCDC3 enables or disables DCDC3.
func (d *Device) SetDCDC3(State bool) {
v := d.GetDCDC13LDO23Switch()
if State == true {
v = (1 << 1) | v
} else {
v = ^(uint8(1) << 1) & v
}
d.SetDCDC13LDO23Switch(v)
}
// Pin is a single pin on AXP192.
type Pin struct {
pin uint8
axp *Device
}
// High sets this GPIO pin to high.
func (p Pin) High() {
switch p.pin {
case 1: // LED
v := p.axp.GetGPIO20SignalStatus()
p.axp.SetGPIO20SignalStatus(v | 0x02)
case 2: // SPK_EN
case 4: // RST
v := p.axp.GetGPIO43SignalStatus()
v |= uint8(0x02)
p.axp.SetGPIO43SignalStatus(v)
}
}
// Low sets this GPIO pin to low.
func (p Pin) Low() {
switch p.pin {
case 1: // LED
v := p.axp.GetGPIO20SignalStatus()
p.axp.SetGPIO20SignalStatus(v & 0xFD)
case 2: // SPK_EN
case 4: // RST
v := p.axp.GetGPIO43SignalStatus()
v &= ^uint8(0x02)
p.axp.SetGPIO43SignalStatus(v)
}
}
// Toggle switches an output pin from low to high or from high to low.
func (p Pin) Toggle() {
switch p.pin {
case 1: // LED
v := p.axp.GetGPIO20SignalStatus()
if (v & 0x02) == 0 {
p.axp.SetGPIO20SignalStatus(v | 0x02)
} else {
p.axp.SetGPIO20SignalStatus(v & 0xFD)
}
case 2: // SPK_EN
case 4: // RST
v := p.axp.GetGPIO43SignalStatus()
if (v & 0x02) == 0 {
v |= uint8(0x02)
} else {
v &= ^uint8(0x02)
}
p.axp.SetGPIO43SignalStatus(v)
}
}
+127
View File
@@ -0,0 +1,127 @@
package axp192
// power supply control class
// 0x00 Power supply status register
// 0x01 Power supply mode/charging status register
// 0x04 OTG VBUS status register
// 0x0609 Data buffer register
// 0x10 EXTEN & DCDC2 switch register
// 0x12 DCDC1/3 & LDO2/3switch register
// 0x23 DCDC2 voltage set register
// 0x25 DCDC2 voltage slope set register
// 0x26 DCDC1voltage set register
// 0x27 DCDC3 voltage set register
// 0x28 LDO2/3 voltage set register
// 0x30 VBUSIPSOUT access set register
// 0x31 VOFF power off voltage set register
// 0x32 Power off、battery detect、CHGLED control register
// 0x33 Charging control register1
// 0x34 Charging control register2
// 0x35 Backup battery charging control register
// 0x36 PEK parameter set register
// 0x37 DCDC switch frequency set register
// 0x38 Battery charging under temperature warning set register
// 0x39 Battery charging over temperature warning set register
// 0x3A APS under voltage Level1 set register
// 0x3B APS under voltage Level2 set register
// 0x3C Battery discharging under temperature warning set register
// 0x3D Battery discharging over temperature warning set register
// 0x80 DCDC mode set register
// 0x82 ADC enable set register 1
// 0x83 ADC enable set register 2
// 0x84 ADC sample frequency set, TS pin control register
// 0x85 GPIO [3:0] input range set register
// 0x8A Timer control register
// 0x8B VBUS monitor set register
// 0x8F Over temperature power off control register
// GPIO control class
// 0x90 GPIO0 control register
// 0x91 GPIO0 LDO mode output voltage set register
// 0x92 GPIO1 control register
// 0x93 GPIO2 control register
// 0x94 GPIO[2:0] signal status register
// 0x95 GPIO[4:3] function control register
// 0x96 GPIO[4:3] signal status register
// 0x97 GPIO[2:0] pull down control register
// 0x98 PWM1 frequency set register
// 0x99 PWM1 duty ratio set register 1
// 0x9A PWM1 duty ratio set register 2
// 0x9B PWM2 frequency set register
// 0x9C PWM2 duty ratio set register 1
// 0x9D PWM2 duty ratio set register 2
// 0x9E GPIO5 control register
// IRQ control class
// 0x40 IRQ enable control register 1
// 0x41 IRQ enable control register 2
// 0x42 IRQ enable control register 3
// 0x43 IRQ enable control register 4
// 0x44 IRQ status register 1
// 0x45 IRQ status register 2
// 0x46 IRQ status register 3
// 0x47 IRQ status register 4
// ADC data class
// 0x56 ACIN voltage ADC data high 8 bit
// 0x57 ACIN voltage ADC data low 4 bit
// 0x58 ACIN current ADC data high 8 bit
// 0x59 ACIN current ADC data low 4 bit
// 0x5A VBUS voltage ADC data high 8 bit
// 0x5B VBUS voltage ADC data low 4 bit
// 0x5C VBUS current ADC data high 8 bit
// 0x5D VBUS current ADC data low 4 bit
// 0x5E AXP192 internal temperature monitor ADC data High 8 bit
// 0x5F AXP192 internal temperature monitor ADC data low 4 bit
// 0x62 TS input ADC data High 8 bitmonitor battery temperature by default
// 0x63 TS input ADC data low 4 bitmonitor battery temperature by default
// 0x64 GPIO0 voltage ADC data high 8 bit
// 0x65 GPIO0 voltage ADC data low 4 bit
// 0x66 GPIO1 voltage ADC data high 8 bit
// 0x67 GPIO1 voltage ADC data low 4 bit
// 0x68 GPIO2 voltage ADC data high 8 bit
// 0x69 GPIO2 voltage ADC data low 4 bit
// 0x6A GPIO[3] voltage ADC data high 8 bit
// 0x6B GPIO[3] voltage ADC data low 4 bit
// 0x70 Battery instantaneous power high 8 bit
// 0x71 Battery instantaneous power middle 8 bit
// 0x72 Battery instantaneous power low 8 bit
// 0x78 Battery voltage high 8 bit
// 0x79 Battery voltage low 4 bit
// 0x7A Battery charging current high 8 bit
// 0x7B Battery charging current low 5 bit
// 0x7C Battery discharging current high 8 bit
// 0x7D Battery discharging current low 5 bit
// 0x7E APS voltage high 8 bit
// 0x7F APS voltage low 4 bit
// 0xB0 Battery charging coulomb counter data register 3
// 0xB1 Battery charging coulomb counter data register 2
// 0xB2 Battery charging coulomb counter data register 1
// 0xB3 Battery charging coulomb counter data register 0
// 0xB4 Battery discharging coulomb counter data register 3
// 0xB5 Battery discharging coulomb counter data register 2
// 0xB6 Battery discharging coulomb counter data register 1
// 0xB7 Battery discharging coulomb counter data register 0
// 0xB8 Coulomb counter control register
const (
// Address is default I2C address.
Address = 0x34
RegPowerSupplyStatus = 0x00
RegDCDC13LDO23Switch = 0x12
RegVbusIPSOutAccessManagement = 0x30
RegBackupBatteryChargingControl = 0x35
RegDCDC2VoltageSet = 0x25
RegDCDC1VoltageSet = 0x26
RegDCDC3VoltageSet = 0x27
RegLDO23VoltageSet = 0x28
RegPEKParameterSet = 0x36
RegADCEnableSet = 0x82
RegGPIO1Control = 0x92
RegGPIO2Control = 0x93
RegGPIO20SignalStatus = 0x94
RegGPIO43FunctionControl = 0x95
RegGPIO43SignalStatus = 0x96
)
+23
View File
@@ -0,0 +1,23 @@
package espat
import (
"time"
"tinygo.org/x/drivers/net"
)
func (d *Device) ConnectToAccessPoint(ssid, pass string, timeout time.Duration) error {
if len(ssid) == 0 {
return net.ErrWiFiMissingSSID
}
if err := d.SetWifiMode(WifiModeClient); err != nil {
return err
}
return d.ConnectToAP(ssid, pass, 10)
}
func (d *Device) Disconnect() error {
return d.DisconnectFromAP()
}
+47 -26
View File
@@ -28,6 +28,8 @@ import (
"tinygo.org/x/drivers/net"
)
const CRLF = "\r\n"
// Device wraps UART connection to the ESP8266/ESP32.
type Device struct {
bus drivers.UART
@@ -37,10 +39,10 @@ type Device struct {
// data received from a TCP/UDP connection forwarded by the ESP8266/ESP32
socketdata []byte
}
// ActiveDevice is the currently configured Device in use. There can only be one.
var ActiveDevice *Device
// dump extra data to console?
Debug bool
}
// New returns a new espat driver. Pass in a fully configured UART bus.
func New(b drivers.UART) *Device {
@@ -48,9 +50,9 @@ func New(b drivers.UART) *Device {
}
// Configure sets up the device for communication.
func (d Device) Configure() {
ActiveDevice = &d
net.ActiveDevice = ActiveDevice
func (d *Device) Configure() {
// set the configured Device in use. There can only be one.
net.UseDriver(d)
}
// Connected checks if there is communication with the ESP8266/ESP32.
@@ -59,10 +61,7 @@ func (d *Device) Connected() bool {
// handle response here, should include "OK"
_, err := d.Response(100)
if err != nil {
return false
}
return true
return err == nil
}
// Write raw bytes to the UART.
@@ -80,21 +79,33 @@ const pause = 300
// Execute sends an AT command to the ESP8266/ESP32.
func (d Device) Execute(cmd string) error {
_, err := d.Write([]byte("AT" + cmd + "\r\n"))
data := "AT" + cmd
if d.Debug {
debugprintln(data)
}
_, err := d.Write([]byte(data + CRLF))
return err
}
// Query sends an AT command to the ESP8266/ESP32 that returns the
// current value for some configuration parameter.
func (d Device) Query(cmd string) (string, error) {
_, err := d.Write([]byte("AT" + cmd + "?\r\n"))
data := "AT" + cmd + "?"
if d.Debug {
debugprintln(data)
}
_, err := d.Write([]byte(data + CRLF))
return "", err
}
// Set sends an AT command with params to the ESP8266/ESP32 for a
// configuration value to be set.
func (d Device) Set(cmd, params string) error {
_, err := d.Write([]byte("AT" + cmd + "=" + params + "\r\n"))
data := "AT" + cmd + "=" + params
if d.Debug {
debugprintln(data)
}
_, err := d.Write([]byte(data + CRLF))
return err
}
@@ -103,6 +114,10 @@ func (d Device) Version() []byte {
d.Execute(Version)
r, err := d.Response(100)
if err != nil {
if d.Debug {
debugprintln(string(r))
}
return []byte("unknown")
}
return r
@@ -152,17 +167,17 @@ func (d *Device) ReadSocket(b []byte) (n int, err error) {
// The call will retry for up to timeout milliseconds before returning nothing.
func (d *Device) Response(timeout int) ([]byte, error) {
// read data
var size int
var start, end int
pause := 100 // pause to wait for 100 ms
retries := timeout / pause
pause := 10 * time.Millisecond
starting := time.Now()
for {
size = d.bus.Buffered()
if size > 0 {
if size := d.bus.Buffered(); size > 0 {
end += size
d.bus.Read(d.response[start:end])
_, err := d.bus.Read(d.response[start:end])
if err != nil {
return nil, err
}
// if "+IPD" then read socket data
if strings.Contains(string(d.response[:end]), "+IPD") {
@@ -172,12 +187,15 @@ func (d *Device) Response(timeout int) ([]byte, error) {
// if "OK" then the command worked
if strings.Contains(string(d.response[:end]), "OK") {
return d.response[start:end], nil
if d.Debug {
debugprintln(string(d.response[:end]))
}
return d.response[:end], nil
}
// if "Error" then the command failed
if strings.Contains(string(d.response[:end]), "ERROR") {
return d.response[start:end], errors.New("response error:" + string(d.response[start:end]))
return d.response[:end], errors.New("response error:" + string(d.response[:end]))
}
// if anything else, then keep reading data in?
@@ -185,12 +203,11 @@ func (d *Device) Response(timeout int) ([]byte, error) {
}
// wait longer?
retries--
if retries == 0 {
return nil, errors.New("response timeout error:" + string(d.response[start:end]))
if time.Since(starting) > time.Duration(timeout)*time.Millisecond {
return nil, errors.New("response timeout error:" + string(d.response[:end]))
}
time.Sleep(time.Duration(pause) * time.Millisecond)
time.Sleep(pause)
}
}
@@ -220,3 +237,7 @@ func (d *Device) parseIPD(end int) error {
func (d *Device) IsSocketDataAvailable() bool {
return len(d.socketdata) > 0 || d.bus.Buffered() > 0
}
func debugprintln(msg string) {
println("[DEBUG] " + msg)
}
+50 -12
View File
@@ -19,6 +19,9 @@ func (d *Device) GetDNS(domain string) (string, error) {
d.Set(TCPDNSLookup, "\""+domain+"\"")
resp, err := d.Response(1000)
if err != nil {
if d.Debug {
println(string(resp))
}
return "", err
}
if !strings.Contains(string(resp), ":") {
@@ -36,13 +39,17 @@ func (d *Device) GetDNS(domain string) (string, error) {
// Currently only supports single connection mode.
func (d *Device) ConnectTCPSocket(addr, port string) error {
protocol := "TCP"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
val := "\"" + protocol + "\"," + addr + "," + port + ",120"
err := d.Set(TCPConnect, val)
if err != nil {
return err
}
_, e := d.Response(3000)
r, e := d.Response(3000)
if e != nil {
if d.Debug {
println(string(r))
}
return e
}
return nil
@@ -51,13 +58,17 @@ func (d *Device) ConnectTCPSocket(addr, port string) error {
// ConnectUDPSocket creates a new UDP connection for the ESP8266/ESP32.
func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
protocol := "UDP"
val := "\"" + protocol + "\",\"" + addr + "\"," + sendport + "," + listenport + ",2"
val := "\"" + protocol + "\"," + addr + "," + sendport + "," + listenport + ",2"
err := d.Set(TCPConnect, val)
if err != nil {
return err
}
_, e := d.Response(3000)
r, e := d.Response(3000)
if e != nil {
if d.Debug {
println(string(r))
}
return e
}
return nil
@@ -67,11 +78,15 @@ func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
// Currently only supports single connection mode.
func (d *Device) ConnectSSLSocket(addr, port string) error {
protocol := "SSL"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
val := "\"" + protocol + "\"," + addr + "," + port + ",120"
d.Set(TCPConnect, val)
// this operation takes longer, so wait up to 6 seconds to complete.
_, err := d.Response(6000)
r, err := d.Response(6000)
if err != nil {
if d.Debug {
println(string(r))
}
return err
}
return nil
@@ -83,8 +98,12 @@ func (d *Device) DisconnectSocket() error {
if err != nil {
return err
}
_, e := d.Response(pause)
r, e := d.Response(pause)
if e != nil {
if d.Debug {
println(string(r))
}
return e
}
return nil
@@ -95,7 +114,11 @@ func (d *Device) DisconnectSocket() error {
func (d *Device) SetMux(mode int) error {
val := strconv.Itoa(mode)
d.Set(TCPMultiple, val)
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err
}
@@ -110,7 +133,11 @@ func (d *Device) GetMux() ([]byte, error) {
func (d *Device) SetTCPTransferMode(mode int) error {
val := strconv.Itoa(mode)
d.Set(TransmissionMode, val)
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err
}
@@ -123,12 +150,19 @@ func (d *Device) GetTCPTransferMode() ([]byte, error) {
// StartSocketSend gets the ESP8266/ESP32 ready to receive TCP/UDP socket data.
func (d *Device) StartSocketSend(size int) error {
val := strconv.Itoa(size)
d.Set(TCPSend, val)
err := d.Set(TCPSend, val)
if err != nil {
return err
}
// when ">" is received, it indicates
// ready to receive data
r, err := d.Response(2000)
r, err := d.Response(500)
if err != nil {
if d.Debug {
println(string(r))
}
return err
}
if strings.Contains(string(r), ">") {
@@ -142,6 +176,10 @@ func (d *Device) StartSocketSend(size int) error {
func (d *Device) EndSocketSend() error {
d.Write([]byte("+++"))
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
println(string(r))
}
return err
}
+53 -8
View File
@@ -25,7 +25,11 @@ func (d *Device) GetWifiMode() ([]byte, error) {
func (d *Device) SetWifiMode(mode int) error {
val := strconv.Itoa(mode)
d.Set(WifiMode, val)
_, err := d.Response(pause)
r, err := d.Response(pause)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -43,8 +47,12 @@ func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
val := "\"" + ssid + "\",\"" + pwd + "\""
d.Set(ConnectAP, val)
_, err := d.Response(ws * 1000)
r, err := d.Response(ws * 1000)
if err != nil {
if d.Debug {
debugprintln(string(r))
}
return err
}
return nil
@@ -53,7 +61,11 @@ func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
// DisconnectFromAP disconnects the ESP8266/ESP32 from the current access point.
func (d *Device) DisconnectFromAP() error {
d.Execute(Disconnect)
_, err := d.Response(1000)
r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -68,7 +80,11 @@ func (d *Device) GetClientIP() (string, error) {
func (d *Device) SetClientIP(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(ConnectAP, val)
_, err := d.Response(500)
r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -78,6 +94,10 @@ func (d *Device) SetClientIP(ipaddr string) error {
func (d *Device) GetAPConfig() (string, error) {
d.Query(SoftAPConfigCurrent)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -89,7 +109,11 @@ func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigCurrent, val)
_, err := d.Response(1000)
r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -97,6 +121,9 @@ func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
func (d *Device) GetAPClients() (string, error) {
d.Query(ListConnectedIP)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -104,6 +131,9 @@ func (d *Device) GetAPClients() (string, error) {
func (d *Device) GetAPIP() (string, error) {
d.Query(SetSoftAPIPCurrent)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -111,7 +141,10 @@ func (d *Device) GetAPIP() (string, error) {
func (d *Device) SetAPIP(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPCurrent, val)
_, err := d.Response(500)
r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -120,6 +153,9 @@ func (d *Device) SetAPIP(ipaddr string) error {
func (d *Device) GetAPConfigFlash() (string, error) {
d.Query(SoftAPConfigFlash)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -132,7 +168,10 @@ func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigFlash, val)
_, err := d.Response(1000)
r, err := d.Response(1000)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
@@ -141,6 +180,9 @@ func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
func (d *Device) GetAPIPFlash() (string, error) {
d.Query(SetSoftAPIPFlash)
r, err := d.Response(100)
if err != nil && d.Debug {
debugprintln(string(r))
}
return string(r), err
}
@@ -149,6 +191,9 @@ func (d *Device) GetAPIPFlash() (string, error) {
func (d *Device) SetAPIPFlash(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPFlash, val)
_, err := d.Response(500)
r, err := d.Response(500)
if err != nil && d.Debug {
debugprintln(string(r))
}
return err
}
+39
View File
@@ -0,0 +1,39 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/apds9960"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
sensor.Configure(apds9960.Configuration{}) // use default settings
if !sensor.Connected() {
println("APDS-9960 not connected!")
return
}
sensor.EnableColor() // enable color engine
for {
if sensor.ColorAvailable() {
r, g, b, c := sensor.ReadColor()
println("Red =", r, "\tGreen =", g, "\tBlue =", b, "\tClear =", c)
}
time.Sleep(time.Millisecond * 100)
}
}
+52
View File
@@ -0,0 +1,52 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/apds9960"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
sensor.Configure(apds9960.Configuration{}) // use default settings
if !sensor.Connected() {
println("APDS-9960 not connected!")
return
}
sensor.EnableGesture() // enable gesture engine
for {
// wave your hand (not too slow) about 10 cm above the sensor
if sensor.GestureAvailable() {
gesture := sensor.ReadGesture()
print("Detected gesture: ")
switch gesture {
case apds9960.GESTURE_UP: // the nRF52 chip is "up"
println("Up")
case apds9960.GESTURE_DOWN:
println("Down")
case apds9960.GESTURE_LEFT:
println("Left")
case apds9960.GESTURE_RIGHT:
println("Right")
}
}
// note: the delay shouldn't be too long, otherwise new gesture data might be lost
time.Sleep(time.Millisecond * 250)
}
}
+40
View File
@@ -0,0 +1,40 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/apds9960"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
// use default settings
sensor.Configure(apds9960.Configuration{})
if !sensor.Connected() {
println("APDS-9960 not connected!")
return
}
sensor.EnableProximity() // enable proximity engine
for {
if sensor.ProximityAvailable() {
p := sensor.ReadProximity()
println("Proximity:", p)
}
time.Sleep(time.Millisecond * 100)
}
}
@@ -0,0 +1,25 @@
package main
import (
"machine"
"time"
axp192 "tinygo.org/x/drivers/axp192/m5stack-core2-axp192"
"tinygo.org/x/drivers/i2csoft"
)
func main() {
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
axp := axp192.New(i2c)
led := axp.LED
for {
led.Low()
time.Sleep(time.Millisecond * 500)
led.High()
time.Sleep(time.Millisecond * 500)
}
}
+3 -2
View File
@@ -113,8 +113,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+3 -2
View File
@@ -99,8 +99,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+3 -2
View File
@@ -88,8 +88,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+3 -2
View File
@@ -108,8 +108,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+3 -2
View File
@@ -129,8 +129,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+3 -2
View File
@@ -91,8 +91,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+24
View File
@@ -0,0 +1,24 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
import (
"machine"
"tinygo.org/x/drivers/ft6336"
"tinygo.org/x/drivers/i2csoft"
"tinygo.org/x/drivers/touch"
)
// InitDisplay initializes the display of each board.
func initDevices() (touch.Pointer, error) {
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
resistiveTouch := ft6336.New(i2c, machine.Pin(39))
resistiveTouch.Configure(ft6336.Config{})
resistiveTouch.SetPeriodActive(0x00)
return resistiveTouch, nil
}
+16
View File
@@ -0,0 +1,16 @@
package main
func main() {
touchScreen, _ := initDevices()
for {
touch := touchScreen.ReadTouchPoint()
if touch.Z > 0 {
//X and Y are 16 bit with 12 bit resolution and need to be scaled for the display size
//Z is 24 bit and is typically > 2000 for a touch
println("touch:", touch.X, touch.Y, touch.Z)
//Example of scaling for m5stack-core2's 320x240 display with 320x270 touch area
println("screen:", (touch.X*320)>>16, (touch.Y*270)>>16)
}
}
}
@@ -0,0 +1,55 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
import (
"image/color"
"machine"
axp192 "tinygo.org/x/drivers/axp192/m5stack-core2-axp192"
"tinygo.org/x/drivers/ft6336"
"tinygo.org/x/drivers/i2csoft"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/touch"
)
// InitDisplay initializes the display of each board.
func initDevices() (touchPaintDisplay, touch.Pointer, error) {
machine.SPI2.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40e6,
})
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
axp := axp192.New(i2c)
led := axp.LED
led.Low()
display := ili9341.NewSPI(
machine.SPI2,
machine.LCD_DC_PIN,
machine.LCD_SS_PIN,
machine.NoPin,
)
// configure display
display.Configure(ili9341.Config{
Width: 320,
Height: 240,
DisplayInversion: true,
})
display.FillScreen(color.RGBA{255, 255, 255, 255})
display.SetRotation(ili9341.Rotation0Mirror)
resistiveTouch := ft6336.New(i2c, machine.Pin(39))
resistiveTouch.Configure(ft6336.Config{})
resistiveTouch.SetPeriodActive(0x00)
return display, resistiveTouch, nil
}
+163
View File
@@ -0,0 +1,163 @@
package main
import (
"image/color"
"math"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/touch"
)
type touchPaintDisplay interface {
drivers.Displayer
FillRectangle(x, y, width, height int16, c color.RGBA) error
DrawRectangle(x, y, w, h int16, c color.RGBA) error
}
var (
white = color.RGBA{255, 255, 255, 255}
black = color.RGBA{0, 0, 0, 255}
red = color.RGBA{255, 0, 0, 255}
green = color.RGBA{0, 255, 0, 255}
blue = color.RGBA{0, 0, 255, 255}
magenta = color.RGBA{255, 0, 255, 255}
yellow = color.RGBA{255, 255, 0, 255}
cyan = color.RGBA{0, 255, 255, 255}
oldColor color.RGBA
currentColor color.RGBA
)
const (
penRadius = 3
boxSize = 30
Xmin = 0
Xmax = 0xFFFF
Ymin = 0
Ymax = 0xFFFF
)
func main() {
display, resistiveTouch, _ := initDevices()
// fill the background and activate the backlight
width, height := display.Size()
display.FillRectangle(0, 0, width, height, black)
// make color selection boxes
display.FillRectangle(0, 0, boxSize, boxSize, red)
display.FillRectangle(boxSize, 0, boxSize, boxSize, yellow)
display.FillRectangle(boxSize*2, 0, boxSize, boxSize, green)
display.FillRectangle(boxSize*3, 0, boxSize, boxSize, cyan)
display.FillRectangle(boxSize*4, 0, boxSize, boxSize, blue)
display.FillRectangle(boxSize*5, 0, boxSize, boxSize, magenta)
display.FillRectangle(boxSize*6, 0, boxSize, boxSize, black)
display.FillRectangle(boxSize*7, 0, boxSize, boxSize, white)
// set the initial color to red and draw a box to highlight it
oldColor = red
currentColor = red
display.DrawRectangle(0, 0, boxSize, boxSize, white)
last := touch.Point{}
// loop and poll for touches, including performing debouncing
debounce := 0
for {
point := resistiveTouch.ReadTouchPoint()
touch := touch.Point{}
if point.Z>>6 > 100 {
rawX := mapval(point.X, Xmin, Xmax, 0, int(width))
rawY := mapval(point.Y, Ymin, Ymax, 0, int(height))
touch.X = rawX
touch.Y = rawY
touch.Z = 1
} else {
touch.X = 0
touch.Y = 0
touch.Z = 0
}
if last.Z != touch.Z {
debounce = 0
last = touch
} else if math.Abs(float64(touch.X-last.X)) > 4 ||
math.Abs(float64(touch.Y-last.Y)) > 4 {
debounce = 0
last = touch
} else if debounce > 1 {
debounce = 0
HandleTouch(display, last)
} else if touch.Z > 0 {
debounce++
} else {
last = touch
debounce = 0
}
}
}
// based on Arduino's "map" function
func mapval(x int, inMin int, inMax int, outMin int, outMax int) int {
return (x-inMin)*(outMax-outMin)/(inMax-inMin) + outMin
}
func HandleTouch(display touchPaintDisplay, touch touch.Point) {
if int16(touch.Y) < boxSize {
oldColor = currentColor
x := int16(touch.X)
switch {
case x < boxSize:
currentColor = red
case x < boxSize*2:
currentColor = yellow
case x < boxSize*3:
currentColor = green
case x < boxSize*4:
currentColor = cyan
case x < boxSize*5:
currentColor = blue
case x < boxSize*6:
currentColor = magenta
case x < boxSize*7:
currentColor = black
case x < boxSize*8:
currentColor = white
}
if oldColor == currentColor {
return
}
display.DrawRectangle((x/boxSize)*boxSize, 0, boxSize, boxSize, white)
switch oldColor {
case red:
x = 0
case yellow:
x = boxSize
case green:
x = boxSize * 2
case cyan:
x = boxSize * 3
case blue:
x = boxSize * 4
case magenta:
x = boxSize * 5
case black:
x = boxSize * 6
case white:
x = boxSize * 7
}
display.FillRectangle(int16(x), 0, boxSize, boxSize, oldColor)
}
if (int16(touch.Y) - penRadius) > boxSize {
display.FillRectangle(
int16(touch.X), int16(touch.Y), penRadius*2, penRadius*2, currentColor)
}
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/hts221"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := hts221.New(machine.I2C1)
sensor.Configure() // power on and calibrate
if !sensor.Connected() {
println("HTS221 not connected!")
return
}
for {
h, _ := sensor.ReadHumidity()
t, _ := sensor.ReadTemperature()
println("h =", float32(h)/100.0, "% / t =", float32(t)/1000.0, "*C")
time.Sleep(time.Second)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/adt7410"
"tinygo.org/x/drivers/i2csoft"
)
func main() {
i2c := i2csoft.New(machine.SCL_PIN, machine.SDA_PIN)
i2c.Configure(i2csoft.I2CConfig{
Frequency: 400e3,
})
sensor := adt7410.New(i2c)
sensor.Configure()
for {
temp := sensor.ReadTempF()
fmt.Printf("temperature: %f\r\n", temp)
time.Sleep(time.Second)
}
}
-30
View File
@@ -1,30 +0,0 @@
//go:build atsamd21
// +build atsamd21
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
backlight = machine.D3
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
}
+6 -7
View File
@@ -2,9 +2,9 @@ package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/ili9341"
)
@@ -16,16 +16,15 @@ var (
green = color.RGBA{0, 255, 0, 255}
)
var (
display *ili9341.Device
)
func main() {
display = initdisplay.InitDisplay()
backlight.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
width, height := display.Size()
display.FillScreen(black)
backlight.High()
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)
-23
View File
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
-30
View File
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
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,
})
}
+41
View File
@@ -0,0 +1,41 @@
//go:build atsamd21
// +build atsamd21
package initdisplay
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var ()
func InitDisplay() *ili9341.Device {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
// configure backlight
backlight := machine.D3
backlight.Configure(machine.PinConfig{machine.PinOutput})
display := ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
// configure display
display.Configure(ili9341.Config{})
backlight.High()
display.SetRotation(ili9341.Rotation270)
return display
}
+43
View File
@@ -0,0 +1,43 @@
//go:build m5stack
// +build m5stack
package initdisplay
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
func InitDisplay() *ili9341.Device {
machine.SPI2.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 40e6,
})
// configure backlight
backlight := machine.LCD_BL_PIN
backlight.Configure(machine.PinConfig{machine.PinOutput})
display := ili9341.NewSPI(
machine.SPI2,
machine.LCD_DC_PIN,
machine.LCD_SS_PIN,
machine.LCD_RST_PIN,
)
// configure display
display.Configure(ili9341.Config{
Width: 320,
Height: 240,
DisplayInversion: true,
})
backlight.High()
display.SetRotation(ili9341.Rotation0Mirror)
return display
}
@@ -0,0 +1,49 @@
//go:build m5stack_core2
// +build m5stack_core2
package initdisplay
import (
"image/color"
"machine"
axp192 "tinygo.org/x/drivers/axp192/m5stack-core2-axp192"
"tinygo.org/x/drivers/i2csoft"
"tinygo.org/x/drivers/ili9341"
)
// InitDisplay initializes the display of each board.
func InitDisplay() *ili9341.Device {
machine.SPI2.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40e6,
})
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
axp := axp192.New(i2c)
led := axp.LED
led.Low()
display := ili9341.NewSPI(
machine.SPI2,
machine.LCD_DC_PIN,
machine.LCD_SS_PIN,
machine.NoPin,
)
// configure display
display.Configure(ili9341.Config{
Width: 320,
Height: 240,
DisplayInversion: true,
})
display.FillScreen(color.RGBA{255, 255, 255, 255})
display.SetRotation(ili9341.Rotation0Mirror)
return display
}
+34
View File
@@ -0,0 +1,34 @@
//go:build pyportal
// +build pyportal
package initdisplay
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
func InitDisplay() *ili9341.Device {
display := ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
// configure backlight
backlight := machine.TFT_BACKLIGHT
backlight.Configure(machine.PinConfig{machine.PinOutput})
// configure display
display.Configure(ili9341.Config{})
backlight.High()
display.SetRotation(ili9341.Rotation270)
return display
}
@@ -1,7 +1,7 @@
//go:build wioterminal
// +build wioterminal
package main
package initdisplay
import (
"machine"
@@ -9,22 +9,31 @@ import (
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
)
func init() {
func InitDisplay() *ili9341.Device {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
// configure backlight
backlight := machine.LCD_BACKLIGHT
backlight.Configure(machine.PinConfig{machine.PinOutput})
display := ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
// configure display
display.Configure(ili9341.Config{})
backlight.High()
display.SetRotation(ili9341.Rotation270)
return display
}
+6 -9
View File
@@ -3,9 +3,9 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/examples/ili9341/pyportal_boing/graphics"
"tinygo.org/x/drivers/ili9341"
)
@@ -44,20 +44,17 @@ var (
palette [16]uint16
)
var (
display *ili9341.Device
)
func main() {
display = initdisplay.InitDisplay()
// configure backlight
backlight.Configure(machine.PinConfig{machine.PinOutput})
// configure display
display.Configure(ili9341.Config{})
print("width, height == ")
width, height := display.Size()
println(width, height)
backlight.High()
display.SetRotation(ili9341.Rotation270)
DrawBackground()
startTime = time.Now().UnixNano()
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
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,
})
}
-30
View File
@@ -1,30 +0,0 @@
//go:build atsamd21
// +build atsamd21
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
backlight = machine.D3
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
}
+6 -7
View File
@@ -2,9 +2,9 @@ package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/ili9341"
)
@@ -16,16 +16,15 @@ var (
white = color.RGBA{255, 255, 255, 255}
)
var (
display *ili9341.Device
)
func main() {
display := initdisplay.InitDisplay()
backlight.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
width, height := display.Size()
display.FillScreen(black)
backlight.High()
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)
-23
View File
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
-30
View File
@@ -1,30 +0,0 @@
//go:build atsamd21
// +build atsamd21
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
backlight = machine.D3
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
}
+6 -5
View File
@@ -3,10 +3,10 @@ package main
import (
"fmt"
"image/color"
"machine"
"strings"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/image/jpeg"
"tinygo.org/x/drivers/image/png"
@@ -20,6 +20,10 @@ var (
green = color.RGBA{0, 255, 0, 255}
)
var (
display *ili9341.Device
)
func main() {
err := run()
for err != nil {
@@ -28,9 +32,7 @@ func main() {
}
func run() error {
backlight.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
display = initdisplay.InitDisplay()
width, height := display.Size()
if width < 320 || height < 240 {
@@ -38,7 +40,6 @@ func run() error {
}
display.FillScreen(black)
backlight.High()
for {
err := drawJpeg(display)
-23
View File
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
-30
View File
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
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,
})
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lps22hb"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := lps22hb.New(machine.I2C1)
sensor.Configure()
if !sensor.Connected() {
println("LPS22HB not connected!")
return
}
for {
p, _ := sensor.ReadPressure()
t, _ := sensor.ReadTemperature()
println("p =", float32(p)/1000.0, "hPa / t =", float32(t)/1000.0, "*C")
time.Sleep(time.Second)
// note: the device would power down itself after each query
}
}
+33 -16
View File
@@ -3,37 +3,54 @@ package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lsm303agr"
)
func main() {
// LSM303AGR/MAG is connected to the I2C0 bus on micro:bit v1 (the same as P19/P20) and v2 (internal)
machine.I2C0.Configure(machine.I2CConfig{})
accel_mag := lsm303agr.New(machine.I2C0)
if !accel_mag.Connected() {
sensor := lsm303agr.New(machine.I2C0)
sensor.Configure(lsm303agr.Configuration{}) //default settings
// you can specify the following options to adjust accuracy, sensor range or save power.
// see https://github.com/tinygo-org/drivers/blob/release/lsm303agr/registers.go for details:
/*
sensor.Configure(lsm303agr.Configuration{
AccelPowerMode: lsm303agr.ACCEL_POWER_NORMAL,
AccelRange: lsm303agr.ACCEL_RANGE_2G,
AccelDataRate: lsm303agr.ACCEL_DATARATE_100HZ,
MagPowerMode: lsm303agr.MAG_POWER_NORMAL,
MagSystemMode: lsm303agr.MAG_SYSTEM_CONTINUOUS,
MagDataRate: lsm303agr.MAG_DATARATE_10HZ,
})
*/
if !sensor.Connected() {
println("LSM303AGR/MAG not connected!")
return
}
accel_mag.Configure(lsm303agr.Configuration{}) //default settings
for {
// accel_x, accel_y, accel_z := sensor.ReadAcceleration()
// println("ACCEL_X:", accel_x/100000, " ACCEL_Y:", accel_y/100000, " ACCEL_Z:", accel_z/100000)
accel_x, accel_y, accel_z := accel_mag.ReadAcceleration()
pitch, roll := accel_mag.ReadPitchRoll()
mag_x, mag_y, mag_z := accel_mag.ReadMagneticField()
heading := accel_mag.ReadCompass()
temp, _ := accel_mag.ReadTemperature()
// mag_x, mag_y, mag_z := sensor.ReadMagneticField()
// println("MAG_X:", mag_x/100000, " MAG_Y:", mag_y/100000, " MAG_Z:", mag_z/100000)
pitch, roll := sensor.ReadPitchRoll()
println("Pitch:", float32(pitch)/100000, " Roll:", float32(roll)/100000)
heading := sensor.ReadCompass()
println("Heading:", float32(heading)/100000, "degrees")
temp, _ := sensor.ReadTemperature()
println("Temperature:", float32(temp)/1000, "*C")
println("ACCEL_X:", accel_x, " ACCEL_Y:", accel_y, " ACCEL_Z:", accel_z)
println("MAG_X:", mag_x, " MAG_Y:", mag_y, " MAG_Z:", mag_z)
println("Pitch:", pitch, " Roll:", roll)
println("Heading:", heading)
println("Temperature:", temp/1000)
println("\n")
time.Sleep(time.Millisecond * 100)
time.Sleep(time.Millisecond * 250)
}
}
+103
View File
@@ -0,0 +1,103 @@
// LSM9DS1, 9 axis Inertial Measurement Unit (IMU)
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/lsm9ds1"
)
const (
PLOTTER = false
SHOW_ACCELERATION = true
SHOW_ROTATION = true
SHOW_MAGNETIC_FIELD = true
SHOW_TEMPERATURE = true
)
func main() {
// I2C configure
machine.I2C0.Configure(machine.I2CConfig{})
// LSM9DS1 setup
device := lsm9ds1.New(machine.I2C0)
err := device.Configure(lsm9ds1.Configuration{
AccelRange: lsm9ds1.ACCEL_2G,
AccelSampleRate: lsm9ds1.ACCEL_SR_119,
GyroRange: lsm9ds1.GYRO_250DPS,
GyroSampleRate: lsm9ds1.GYRO_SR_119,
MagRange: lsm9ds1.MAG_4G,
MagSampleRate: lsm9ds1.MAG_SR_40,
})
if err != nil {
for {
println("Failed to configure", err.Error())
time.Sleep(time.Second)
}
}
for {
if con, err := device.Connected(); !con || err != nil {
println("LSM9DS1 not connected")
time.Sleep(time.Second)
continue
}
ax, ay, az, _ := device.ReadAcceleration()
gx, gy, gz, _ := device.ReadRotation()
mx, my, mz, _ := device.ReadMagneticField()
t, _ := device.ReadTemperature()
if PLOTTER {
printPlotter(ax, ay, az, gx, gy, gz, mx, my, mz, t)
time.Sleep(time.Millisecond * 100)
} else {
printMonitor(ax, ay, az, gx, gy, gz, mx, my, mz, t)
time.Sleep(time.Millisecond * 1000)
}
}
}
// Arduino IDE's Serial Plotter
func printPlotter(ax, ay, az, gx, gy, gz, mx, my, mz, t int32) {
if SHOW_ACCELERATION {
fmt.Printf("AX:%f, AY:%f, AZ:%f,", axis(ax), axis(ay), axis(az))
}
if SHOW_ROTATION {
fmt.Printf("GX:%f, GY:%f, GZ:%f,", axis(gx), axis(gy), axis(gz))
}
if SHOW_MAGNETIC_FIELD {
fmt.Printf("MX:%d, MY:%d, MZ:%d,", mx, my, mz)
}
if SHOW_TEMPERATURE {
fmt.Printf("T:%f", float32(t)/1000)
}
println()
}
// Any Serial Monitor
func printMonitor(ax, ay, az, gx, gy, gz, mx, my, mz, t int32) {
if SHOW_ACCELERATION {
fmt.Printf("Acceleration (g): %f, %f, %f\r\n", axis(ax), axis(ay), axis(az))
}
if SHOW_ROTATION {
fmt.Printf("Rotation (dps): %f, %f, %f\r\n", axis(gx), axis(gy), axis(gz))
}
if SHOW_MAGNETIC_FIELD {
fmt.Printf("Magnetic field (nT): %d, %d, %d\r\n", mx, my, mz)
}
if SHOW_TEMPERATURE {
fmt.Printf("Temperature C: %f\r\n", float32(t)/1000)
}
println()
}
func axis(raw int32) float32 {
return float32(raw) / 1000000
}
+68
View File
@@ -0,0 +1,68 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/pca9685"
)
func main() {
const (
// Default address on most breakout boards.
pcaAddr = 0x40
)
err := machine.I2C0.Configure(machine.I2CConfig{})
if err != nil {
panic(err.Error())
}
d := pca9685.New(machine.I2C0, 0x40)
err = d.IsConnected()
if err != nil {
panic(err.Error())
}
err = d.Configure(pca9685.PWMConfig{Period: 1e9 / 200}) // 200Hz PWM
if err != nil {
panic(err.Error())
}
var value uint32
step := d.Top() / 5
for {
for value = 0; value <= d.Top(); value += step {
d.SetAll(value)
dc := 100 * value / d.Top()
println("set dc @", dc, "%")
time.Sleep(800 * time.Millisecond)
}
}
}
// ScanI2CDev finds I2C devices on the bus and rreturns them inside
// a slice. If slice is nil then no devices were found.
func ScanI2CDev(bus machine.I2C) (addrs []uint8) {
var addr, count uint8
var err error
w := []byte{1}
// Count devices in first scan
for addr = 1; addr < 127; addr++ {
err = bus.Tx(uint16(addr), w, nil)
if err == nil {
count++
}
}
if count == 0 {
return nil
}
// Allocate slice and populate slice with addresses
addrs = make([]uint8, count)
count = 0
for addr = 1; addr < 127; addr++ {
err = bus.Tx(uint16(addr), w, nil)
if err == nil && count < uint8(len(addrs)) {
addrs[count] = addr
count++
}
}
return addrs
}
+1 -1
View File
@@ -65,7 +65,7 @@ func run() error {
}
net.UseDriver(rtl)
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -74,7 +74,7 @@ func run() error {
}
net.UseDriver(rtl)
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -47,7 +47,7 @@ func run() error {
}
net.UseDriver(rtl)
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -47,7 +47,7 @@ func run() error {
}
net.UseDriver(rtl)
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -76,7 +76,7 @@ func run() error {
net.UseDriver(rtl)
http.SetBuf(buf[:])
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -43,7 +43,7 @@ func run() error {
net.UseDriver(rtl)
http.SetBuf(buf[:])
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
@@ -74,7 +74,7 @@ func run() error {
http.SetBuf(buf[:])
fmt.Fprintf(terminal, "ConnectToAP()\r\n")
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -43,7 +43,7 @@ func run() error {
net.UseDriver(rtl)
http.SetBuf(buf[:])
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+1 -1
View File
@@ -43,7 +43,7 @@ func run() error {
}
http.UseDriver(rtl)
err = rtl.ConnectToAP(ssid, password)
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
if err != nil {
return err
}
+30
View File
@@ -0,0 +1,30 @@
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/shtc3"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := shtc3.New(machine.I2C0)
for {
sensor.WakeUp()
temp, humidity, _ := sensor.ReadTemperatureHumidity()
t := fmt.Sprintf("%.2f", float32(temp)/1000)
h := fmt.Sprintf("%.2f", float32(humidity)/100)
println("Temperature:", t, "°C")
println("Humidity", h, "%")
sensor.Sleep()
time.Sleep(2 * time.Second)
}
}
@@ -0,0 +1,80 @@
package main
// This example will periodically enable Continuous "Preamble" and "Wave" modes on 868.1 Mhz
import (
"machine"
"time"
rfswitch "tinygo.org/x/drivers/examples/sx126x/rfswitch"
"tinygo.org/x/drivers/sx126x"
)
const FREQ = 868100000
var (
loraRadio *sx126x.Device
)
func main() {
println("\n# TinyGo Lora continuous Wave/Preamble test")
println("# -----------------------------------------")
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
// Create the driver
loraRadio = sx126x.New(machine.SPI3)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create RF Switch
var radioSwitch rfswitch.CustomSwitch
loraRadio.SetRfSwitch(radioSwitch)
state := loraRadio.DetectDevice()
if !state {
panic("sx126x not detected. ")
}
// Prepare for Lora operation
loraConf := sx126x.LoraConfig{
Freq: FREQ,
Bw: sx126x.SX126X_LORA_BW_500_0,
Sf: sx126x.SX126X_LORA_SF9,
Cr: sx126x.SX126X_LORA_CR_4_7,
HeaderType: sx126x.SX126X_LORA_HEADER_EXPLICIT,
Preamble: 12,
Ldr: sx126x.SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF,
Iq: sx126x.SX126X_LORA_IQ_STANDARD,
Crc: sx126x.SX126X_LORA_CRC_ON,
SyncWord: sx126x.SX126X_LORA_MAC_PRIVATE_SYNCWORD,
LoraTxPowerDBm: 14,
}
loraRadio.LoraConfig(loraConf)
// Although LoraConfig has already configured most of Lora settings,
// the following lines are still required to enable Continuous Preamble/Wave
loraRadio.SetPacketType(sx126x.SX126X_PACKET_TYPE_LORA)
loraRadio.SetRfFrequency(loraConf.Freq)
loraRadio.SetModulationParams(loraConf.Sf, loraConf.Bw, loraConf.Cr, loraConf.Ldr)
loraRadio.SetTxParams(loraConf.LoraTxPowerDBm, sx126x.SX126X_PA_RAMP_200U)
for {
println("2 seconds in Continuous Preamble")
loraRadio.SetStandby()
loraRadio.SetTxContinuousPreamble()
time.Sleep(2 * time.Second)
println("Continuous Preamble Stopped")
loraRadio.SetStandby()
time.Sleep(10 * time.Second)
println("2 seconds in Continuous Wave")
loraRadio.SetTxContinuousWave()
time.Sleep(2 * time.Second)
println(" Continuous Wave Stopped")
loraRadio.SetStandby()
time.Sleep(60 * time.Second)
}
}
+98
View File
@@ -0,0 +1,98 @@
package main
// In this example, a Lora packet will be sent every 10s
// module will be in RX mode between two transmissions
import (
"device/stm32"
"machine"
"runtime/interrupt"
"time"
rfswitch "tinygo.org/x/drivers/examples/sx126x/rfswitch"
"tinygo.org/x/drivers/sx126x"
)
const FREQ = 868100000
const (
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx126x.Device
txmsg = []byte("Hello TinyGO")
)
// radioIntHandler will take care of radio interrupts
func radioIntHandler(intr interrupt.Interrupt) {
loraRadio.HandleInterrupt()
}
func main() {
println("\n# TinyGo Lora RX/TX test")
println("# ----------------------")
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
// Create the driver
loraRadio = sx126x.New(machine.SPI3)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create RF Switch
var radioSwitch rfswitch.CustomSwitch
loraRadio.SetRfSwitch(radioSwitch)
// Detect the device
state := loraRadio.DetectDevice()
if !state {
panic("sx126x not detected.")
}
// Add interrupt handler for Radio IRQs
intr := interrupt.New(stm32.IRQ_Radio_IRQ_Busy, radioIntHandler)
intr.Enable()
loraConf := sx126x.LoraConfig{
Freq: FREQ,
Bw: sx126x.SX126X_LORA_BW_500_0,
Sf: sx126x.SX126X_LORA_SF9,
Cr: sx126x.SX126X_LORA_CR_4_7,
HeaderType: sx126x.SX126X_LORA_HEADER_EXPLICIT,
Preamble: 12,
Ldr: sx126x.SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF,
Iq: sx126x.SX126X_LORA_IQ_STANDARD,
Crc: sx126x.SX126X_LORA_CRC_ON,
SyncWord: sx126x.SX126X_LORA_MAC_PRIVATE_SYNCWORD,
LoraTxPowerDBm: 20,
}
loraRadio.LoraConfig(loraConf)
var count uint
for {
tStart := time.Now()
// Blocking RX for LORA_DEFAULT_RXTIMEOUT_MS
println("Start Lora RX for 10 sec")
for int(time.Now().Sub(tStart).Seconds()) < 10 {
buf, err := loraRadio.LoraRx(LORA_DEFAULT_RXTIMEOUT_MS)
if err != nil {
println("RX Error: ", err)
} else if buf != nil {
println("Packet Received: len=", len(buf), string(buf))
}
}
println("END Lora RX")
println("LORA TX size=", len(txmsg))
err := loraRadio.LoraTx(txmsg, LORA_DEFAULT_TXTIMEOUT_MS)
if err != nil {
println("TX Error:", err)
}
count++
}
}
+61
View File
@@ -0,0 +1,61 @@
//go:build gnse
// +build gnse
/*
Generic Node Sensor Edition
RFSwitch
Disable Switch : PB8=OFF PA0=OFF PA1=OFF
Enable RX : PB8=ON PA0=ON PA1=OFF
Enable TX RFO LP : PB8=ON PA0=ON PA1=ON
Enable TX RFO HP : PB8=ON PA0=OFF PA1=ON
*/
package rfswitch
import (
"machine"
"tinygo.org/x/drivers/sx126x"
)
type CustomSwitch struct {
}
var (
rfstate int
)
func (s CustomSwitch) InitRFSwitch() {
machine.RF_FE_CTRL1.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RF_FE_CTRL2.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RF_FE_CTRL3.Configure(machine.PinConfig{Mode: machine.PinOutput})
rfstate = -1 //Unknown
}
func (s CustomSwitch) SetRfSwitchMode(mode int) error {
if mode == rfstate {
return nil
}
switch mode {
case sx126x.RFSWITCH_TX_HP:
machine.RF_FE_CTRL1.Set(false)
machine.RF_FE_CTRL2.Set(true)
machine.RF_FE_CTRL3.Set(true)
case sx126x.RFSWITCH_TX_LP:
machine.RF_FE_CTRL1.Set(true)
machine.RF_FE_CTRL2.Set(true)
machine.RF_FE_CTRL3.Set(true)
case sx126x.RFSWITCH_RX:
machine.RF_FE_CTRL1.Set(true)
machine.RF_FE_CTRL2.Set(false)
machine.RF_FE_CTRL3.Set(true)
}
rfstate = mode
return nil
}
+43
View File
@@ -0,0 +1,43 @@
//go:build lorae5
// +build lorae5
package radio
/*
/!\ LoRa-E5 module ONLY transmits through RFO_HP:
Receive: PA4=1, PA5=0
Transmit(high output power, SMPS mode): PA4=0, PA5=1
*/
import (
"errors"
"machine"
"tinygo.org/x/drivers/sx126x"
)
type CustomSwitch struct {
}
func (s CustomSwitch) InitRFSwitch() {
machine.PA4.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.PB5.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
func (s CustomSwitch) SetRfSwitchMode(mode int) error {
switch mode {
case sx126x.RFSWITCH_RX:
machine.PA4.Set(true)
machine.PB5.Set(false)
case sx126x.RFSWITCH_TX_LP:
errors.New("RFSWITCH_TX_LP not supported ")
case sx126x.RFSWITCH_TX_HP:
machine.PA4.Set(false)
machine.PB5.Set(true)
}
return nil
}
+55
View File
@@ -0,0 +1,55 @@
//go:build nucleowl55jc
// +build nucleowl55jc
/*
Nucleo WL55JC1
RFSwitch
+-----------+---------+------------+------------+
| | FE_CTRL1 | FE_CTRL2 | FE_CTRL3 |
| | (PC4) | (PC5) | (PC3) |
+-----------+----------+-----------+------------+
| TX_HP | LOW | HIGH | HIGH |
| TX_LP | HIGH | HIGH | HIGH |
| RX | HIGH | LOW | HIGH |
+-----------+----------+-----------+------------+
*/
package rfswitch
import (
"machine"
"tinygo.org/x/drivers/sx126x"
)
type CustomSwitch struct {
}
func (s CustomSwitch) InitRFSwitch() {
machine.PC4.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.PC5.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.PC3.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
func (s CustomSwitch) SetRfSwitchMode(mode int) error {
switch mode {
case sx126x.RFSWITCH_TX_HP:
machine.PC4.Set(false)
machine.PC5.Set(true)
machine.PC3.Set(true)
case sx126x.RFSWITCH_TX_LP:
machine.PC4.Set(true)
machine.PC5.Set(true)
machine.PC3.Set(true)
case sx126x.RFSWITCH_RX:
machine.PC4.Set(true)
machine.PC5.Set(false)
machine.PC3.Set(true)
}
return nil
}
+28
View File
@@ -0,0 +1,28 @@
//go:build espat
// +build espat
package main
import (
"machine"
"tinygo.org/x/drivers/espat"
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func initAdaptor() *espat.Device {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
adaptor = espat.New(uart)
adaptor.Configure()
return adaptor
}
+111
View File
@@ -0,0 +1,111 @@
// This example opens a TCP connection and sends some data,
// for the purpose of testing speed and connectivity.
//
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
//
package main
import (
"bytes"
"fmt"
"time"
"tinygo.org/x/drivers/net"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the server aka "hub". Replace with your own info.
const serverIP = ""
var buf = &bytes.Buffer{}
func main() {
initAdaptor()
connectToAP()
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
println("Done.")
}
func sendBatch() {
// make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
message("---------------\r\nDialing TCP connection")
conn, err := net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
message(err.Error())
time.Sleep(5 * time.Second)
}
n := 0
w := 0
start := time.Now()
// send data
message("Sending data")
for i := 0; i < 1000; i++ {
buf.Reset()
fmt.Fprint(buf,
"\r---------------------------- i == ", i, " ----------------------------"+
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
continue
}
n += w
}
buf.Reset()
ms := time.Now().Sub(start).Milliseconds()
fmt.Fprint(buf, "\nWrote ", n, " bytes in ", ms, " ms\r\n")
message(buf.String())
if _, err := conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, err := adaptor.GetClientIP()
for ; err != nil; ip, err = adaptor.GetClientIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message(ip)
}
func message(msg string) {
println(msg, "\r")
}
+77
View File
@@ -0,0 +1,77 @@
//go:build rtl8720dn
// +build rtl8720dn
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
adaptor *rtl8720dn.RTL8720DN
uart UARTx
)
func initAdaptor() *rtl8720dn.RTL8720DN {
adaptor, err := setupRTL8720DN()
if err != nil {
return nil
}
net.UseDriver(adaptor)
return adaptor
}
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)
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
}
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)
}
+36
View File
@@ -0,0 +1,36 @@
//go:build wifinina
// +build wifinina
package main
import (
"machine"
"tinygo.org/x/drivers/wifinina"
)
var (
// default interface for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// ESP32/ESP8266 chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
func initAdaptor() *wifinina.Device {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
return adaptor
}
+7 -11
View File
@@ -128,19 +128,15 @@ func waitSerial() {
// connect to access point
func connectToAP() {
if len(ssid) == 0 || len(pass) == 0 {
for {
println("Connection failed: Either ssid or password not set")
time.Sleep(10 * time.Second)
}
}
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
println("Connected.")
}
+9 -13
View File
@@ -132,22 +132,18 @@ func waitSerial() {
// connect to access point
func connectToAP() {
if len(ssid) == 0 || len(pass) == 0 {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println("Connection failed: Either ssid or password not set")
time.Sleep(10 * time.Second)
println(err)
time.Sleep(1 * time.Second)
}
}
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
time.Sleep(2 * time.Second)
println("Connected.")
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
+8 -6
View File
@@ -104,14 +104,16 @@ func main() {
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
+8 -5
View File
@@ -116,13 +116,16 @@ func publishing() {
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
+9 -12
View File
@@ -151,21 +151,18 @@ func clearBuffer() {
// connect to access point
func connectToAP() {
if len(ssid) == 0 || len(pass) == 0 {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println("Connection failed: Either ssid or password not set")
time.Sleep(10 * time.Second)
println(err)
time.Sleep(1 * time.Second)
}
}
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
+91
View File
@@ -0,0 +1,91 @@
//go:build nano_rp2040
// +build nano_rp2040
// This examples shows how to control RGB LED connected to
// NINA-W102 chip on Arduino Nano RP2040 Connect board
// Built-in LED code added for API comparison
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/wifinina"
)
const (
LED = machine.LED
// Arduino Nano RP2040 Connect board RGB LED pins
// See https://docs.arduino.cc/static/3525d638b5c76a2d19588d6b41cd02a0/ABX00053-full-pinout.pdf
LED_R wifinina.Pin = 27
LED_G wifinina.Pin = 25
LED_B wifinina.Pin = 26
)
var (
// these are the default pins for the Arduino Nano-RP2040 Connect
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
device *wifinina.Device
)
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
device = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
device.Configure()
time.Sleep(time.Second)
LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
LED_R.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
LED_G.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
LED_B.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
}
func main() {
setup()
LED.Low() // OFF
LED_R.High() // OFF
LED_G.High() // OFF
LED_B.High() // OFF
go func() {
for {
LED.Low()
time.Sleep(time.Second)
LED.High()
time.Sleep(time.Second)
}
}()
for {
LED_R.Low() // ON
time.Sleep(time.Second)
LED_R.High() // OFF
LED_G.Low() // ON
time.Sleep(time.Second)
LED_G.High() // OFF
LED_B.Low() // ON
time.Sleep(time.Second)
LED_B.High() // OFF
}
}
+10 -7
View File
@@ -113,14 +113,17 @@ func sendBatch() {
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
message("Connected.")
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
+9 -12
View File
@@ -122,21 +122,18 @@ func makeHTTPSRequest() {
// connect to access point
func connectToAP() {
if len(ssid) == 0 || len(pass) == 0 {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println("Connection failed: Either ssid or password not set")
time.Sleep(10 * time.Second)
println(err)
time.Sleep(1 * time.Second)
}
}
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
+10 -8
View File
@@ -76,15 +76,17 @@ func main() {
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
message("Connected.")
time.Sleep(2 * time.Second)
println("Connected.")
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
+9 -13
View File
@@ -124,22 +124,18 @@ func makeHTTPRequest() {
// connect to access point
func connectToAP() {
if len(ssid) == 0 || len(pass) == 0 {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println("Connection failed: Either ssid or password not set")
time.Sleep(10 * time.Second)
println(err)
time.Sleep(1 * time.Second)
}
}
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
time.Sleep(2 * time.Second)
println("Connected.")
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
+44
View File
@@ -0,0 +1,44 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/xpt2046"
)
func main() {
clk := machine.GPIO0
cs := machine.GPIO1
din := machine.GPIO2
dout := machine.GPIO3
irq := machine.GPIO4
touchScreen := xpt2046.New(clk, cs, din, dout, irq)
touchScreen.Configure(&xpt2046.Config{
Precision: 10, //Maximum number of samples for a single ReadTouchPoint to improve accuracy.
})
for {
//Wait for a touch
for !touchScreen.Touched() {
time.Sleep(50 * time.Millisecond)
}
touch := touchScreen.ReadTouchPoint()
//X and Y are 16 bit with 12 bit resolution and need to be scaled for the display size
//Z is 24 bit and is typically > 2000 for a touch
println("touch:", touch.X, touch.Y, touch.Z)
//Example of scaling for a 240x320 display
println("screen:", (touch.X*240)>>16, (touch.Y*320)>>16)
//Wait for touch to end
for touchScreen.Touched() {
time.Sleep(50 * time.Millisecond)
}
}
}
+107
View File
@@ -0,0 +1,107 @@
// Package ft6336 provides a driver for the FT6336 I2C Self-Capacitive touch
// panel controller.
//
// Datasheet: https://focuslcds.com/content/FT6236.pdf
//
package ft6336
import (
"machine"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/touch"
)
// Device wraps FT6336 I2C Self-Capacitive touch
type Device struct {
bus drivers.I2C
buf []byte
Address uint8
intPin machine.Pin
}
// New returns FT6336 device for the provided I2C bus using default address.
func New(i2c drivers.I2C, intPin machine.Pin) *Device {
return &Device{
bus: i2c,
buf: make([]byte, 11),
Address: Address,
intPin: intPin,
}
}
// Config contains settings for FT6636.
type Config struct {
}
// Configure the FT6336 device.
func (d *Device) Configure(config Config) error {
d.write1Byte(0xA4, 0x00)
d.intPin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
return nil
}
// SetGMode sets interrupt mode.
// 0x00 : Interrupt Polling mode
// 0x01 : Interrupt Trigger mode (default)
func (d *Device) SetGMode(v uint8) {
d.write1Byte(RegGMode, v)
}
// GetGMode gets interrupt mode.
func (d *Device) GetGMode() uint8 {
return d.read8bit(RegGMode)
}
// SetPeriodActive sets report rate in Active mode.
func (d *Device) SetPeriodActive(v uint8) {
d.write1Byte(RegPeriodActive, v)
}
// GetPeriodActive gets report rate in Active mode.
func (d *Device) GetPeriodActive() uint8 {
return d.read8bit(RegPeriodActive)
}
// GetFirmwareID gets firmware version.
func (d *Device) GetFirmwareID() uint8 {
return d.read8bit(RegFirmid)
}
// Read reads the registers.
func (d *Device) Read() []byte {
d.bus.Tx(uint16(d.Address), []byte{0x02}, d.buf[:])
return d.buf[:]
}
// ReadTouchPoint reads a single touch.Point from the device. The maximum value
// for each touch.Point is 0xFFFF.
func (d *Device) ReadTouchPoint() touch.Point {
d.Read()
z := 0xFFFFF
if d.buf[0] == 0 {
z = 0
}
//Scale X&Y to 16 bit for consistency across touch drivers
return touch.Point{
X: (int(d.buf[1]&0x0F)<<8 + int(d.buf[2])) * ((1 << 16) / 320),
Y: (int(d.buf[3]&0x0F)<<8 + int(d.buf[4])) * ((1 << 16) / 270),
Z: z,
}
}
// Touched returns if touched or not.
func (d *Device) Touched() bool {
p := d.ReadTouchPoint()
return p.Z > 0
}
func (d *Device) write1Byte(reg, data uint8) {
d.bus.WriteRegister(d.Address, reg, []byte{data})
}
func (d *Device) read8bit(reg uint8) uint8 {
d.bus.ReadRegister(d.Address, reg, d.buf[:1])
return d.buf[0]
}
+49
View File
@@ -0,0 +1,49 @@
package ft6336
// 0x00 DEV_MODE
// 0x01 GEST_ID
// 0x02 TD_STATUS
// 0x03 P1_XH
// 0x04 P1_XL
// 0x05 P1_YH
// 0x06 P1_YL
// 0x07 P1_WEIGHT
// 0x08 P1_MISC
// 0x09 P2_XH
// 0x0A P2_XL
// 0x0B P2_YH
// 0x0C P2_YL
// 0x0D P2_WEIGHT
// 0x0E P2_MISC
// 0x80 TH_GROUP
// 0x85 TH_DIFF
// 0x86 CTRL
// 0x87 TIMEENTERMONITOR
// 0x88 PERIODACTIVE
// 0x89 PERIODMONITOR
// 0x91 RADIAN_VALUE
// 0x92 OFFSET_LEFT_RIGHT
// 0x93 OFFSET_UP_D
// 0x94 DISTANCE_LE
// 0x95 DISTANCE_UP
// 0x96 DISTANCE_ZO
// ...
// 0xA1 LIB_VER_H
// 0xA2 LIB_VER_L
// 0xA3 CIPHER
// 0xA4 G_MODE
// 0xA5 PWR_MODE
// 0xA6 FIRMID
// 0xA8 FOCALTECH_ID
// ...
// 0xAF RELEASE_CODE_ID
// ...
// 0xBC STATE
const (
Address = 0x38
RegPeriodActive = 0x88
RegGMode = 0xA4
RegFirmid = 0xA6
)
+3 -1
View File
@@ -105,7 +105,8 @@ func (g *GPIO) Read(data []byte) (n int, err error) {
data[i] = g.read()
n++
}
g.reconfigureGPIOMode(machine.PinInput)
g.rw.Low()
g.reconfigureGPIOMode(machine.PinOutput)
return n, nil
}
@@ -113,6 +114,7 @@ func (g *GPIO) read4BitMode() byte {
g.en.High()
data := (g.pins() << 4 & 0xF0)
g.en.Low()
g.en.High()
data |= (g.pins() & 0x0F)
g.en.Low()
+1 -1
View File
@@ -126,7 +126,7 @@ func (d *Device) Configure(cfg Config) error {
}
if d.datalength == DATA_LENGTH_4BIT {
d.bus.Write([]byte{DATA_LENGTH_4BIT >> 4})
d.bus.Write([]byte{DATA_LENGTH_4BIT})
}
// Busy flag is now accessible
+1 -1
View File
@@ -26,7 +26,7 @@ const (
FUNCTION_MODE = 0x20
DATA_LENGTH_8BIT = FUNCTION_MODE | 0x10
DATA_LENGTH_4BIT = FUNCTION_MODE | 0x0
DATA_LENGTH_4BIT = FUNCTION_MODE | 0x2
TWO_LINE = FUNCTION_MODE | 0x8
ONE_LINE = FUNCTION_MODE | 0x0
FONT_5X10 = FUNCTION_MODE | 0x4
+4 -3
View File
@@ -101,7 +101,7 @@ func (d *Device) Configure(cfg Config) error {
return nil
}
// ClearDisplay clears all texts on the display.
// ClearDisplay clears all texts on the display and sets the cursor back to position (0, 0).
func (d *Device) ClearDisplay() {
d.sendCommand(DISPLAY_CLEAR)
d.cursor.x = 0
@@ -119,7 +119,8 @@ func (d *Device) Home() {
// SetCursor sets the cursor to a specific position (x, y).
//
// if y (row) is set larger than actual rows, it would be set to 0.
// For example, on 16x2 LCDs the range of x (column) is 0~15 and y (row) is 0~1.
// if y is larger than actual rows, it would be set to 0 (restart from first row).
func (d *Device) SetCursor(x, y uint8) {
rowOffset := []uint8{0x0, 0x40, 0x14, 0x54}
if y > (d.height - 1) {
@@ -139,11 +140,11 @@ func (d *Device) Print(data []byte) {
if chr == '\n' {
d.newLine()
} else {
d.cursor.x++
if d.cursor.x >= d.width {
d.newLine()
}
d.sendData(uint8(rune(chr)))
d.cursor.x++
}
}
}
+178
View File
@@ -0,0 +1,178 @@
// Package hts221 implements a driver for HTS221,
// a capacitive digital sensor for relative humidity and temperature.
//
// Datasheet: https://www.st.com/resource/en/datasheet/hts221.pdf
//
package hts221
import (
"errors"
"tinygo.org/x/drivers"
)
// Device wraps an I2C connection to a HTS221 device.
type Device struct {
bus drivers.I2C
Address uint8
humiditySlope float32
humidityZero float32
temperatureSlope float32
temperatureZero float32
}
// New creates a new HTS221 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus drivers.I2C) Device {
return Device{bus: bus, Address: HTS221_ADDRESS}
}
// Connected returns whether HTS221 has been found.
// It does a "who am I" request and checks the response.
func (d *Device) Connected() bool {
data := []byte{0}
d.bus.ReadRegister(d.Address, HTS221_WHO_AM_I_REG, data)
return data[0] == 0xBC
}
// Power is for turn on/off the HTS221 device
func (d *Device) Power(status bool) {
data := []byte{0}
if status {
data[0] = 0x84
}
d.bus.WriteRegister(d.Address, HTS221_CTRL1_REG, data)
}
// ReadHumidity returns the relative humidity in percent * 100.
// Returns an error if the device is not turned on.
func (d *Device) ReadHumidity() (humidity int32, err error) {
err = d.waitForOneShot(0x02)
if err != nil {
return
}
// read data and calibrate
data := []byte{0, 0}
d.bus.ReadRegister(d.Address, HTS221_HUMID_OUT_REG, data[:1])
d.bus.ReadRegister(d.Address, HTS221_HUMID_OUT_REG+1, data[1:])
hValue := readInt(data[1], data[0])
hValueCalib := float32(hValue)*d.humiditySlope + d.humidityZero
return int32(hValueCalib * 100), nil
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
// Returns an error if the device is not turned on.
func (d *Device) ReadTemperature() (temperature int32, err error) {
err = d.waitForOneShot(0x01)
if err != nil {
return
}
// read data and calibrate
data := []byte{0, 0}
d.bus.ReadRegister(d.Address, HTS221_TEMP_OUT_REG, data[:1])
d.bus.ReadRegister(d.Address, HTS221_TEMP_OUT_REG+1, data[1:])
tValue := readInt(data[1], data[0])
tValueCalib := float32(tValue)*d.temperatureSlope + d.temperatureZero
return int32(tValueCalib * 1000), nil
}
// Resolution sets the HTS221's resolution mode.
// The higher resolutions are more accurate but comsume more power (see datasheet).
// The number of averaged samples will be (h + 2) ^ 2, (t + 1) ^ 2
//
func (d *Device) Resolution(h uint8, t uint8) {
if h > 7 {
h = 3 // default
}
if t > 7 {
t = 3 // default
}
d.bus.WriteRegister(d.Address, HTS221_AV_CONF_REG, []byte{h<<3 | t})
}
// private functions
// read factory calibration data
func (d *Device) calibration() {
h0rH, h1rH := []byte{0}, []byte{0}
t0degC, t1degC := []byte{0}, []byte{0}
t1t0msb := []byte{0}
h0t0Out, h1t0Out := []byte{0, 0}, []byte{0, 0}
t0Out, t1Out := []byte{0, 0}, []byte{0, 0}
d.bus.ReadRegister(d.Address, HTS221_H0_rH_x2_REG, h0rH)
d.bus.ReadRegister(d.Address, HTS221_H1_rH_x2_REG, h1rH)
d.bus.ReadRegister(d.Address, HTS221_T0_degC_x8_REG, t0degC)
d.bus.ReadRegister(d.Address, HTS221_T1_degC_x8_REG, t1degC)
d.bus.ReadRegister(d.Address, HTS221_T1_T0_MSB_REG, t1t0msb)
d.bus.ReadRegister(d.Address, HTS221_H0_T0_OUT_REG, h0t0Out[:1])
d.bus.ReadRegister(d.Address, HTS221_H0_T0_OUT_REG+1, h0t0Out[1:])
d.bus.ReadRegister(d.Address, HTS221_H1_T0_OUT_REG, h1t0Out[:1])
d.bus.ReadRegister(d.Address, HTS221_H1_T0_OUT_REG+1, h1t0Out[1:])
d.bus.ReadRegister(d.Address, HTS221_T0_OUT_REG, t0Out[:1])
d.bus.ReadRegister(d.Address, HTS221_T0_OUT_REG+1, t0Out[1:])
d.bus.ReadRegister(d.Address, HTS221_T1_OUT_REG, t1Out[:1])
d.bus.ReadRegister(d.Address, HTS221_T1_OUT_REG+1, t1Out[1:])
h0rH_v := float32(h0rH[0]) / 2.0
h1rH_v := float32(h1rH[0]) / 2.0
t0degC_v := float32(readUint(t1t0msb[0]&0x03, t0degC[0])) / 8.0
t1degC_v := float32(readUint(t1t0msb[0]&0x0C>>2, t1degC[0])) / 8.0
h0t0Out_v := float32(readInt(h0t0Out[1], h0t0Out[0]))
h1t0Out_v := float32(readInt(h1t0Out[1], h1t0Out[0]))
t0Out_v := float32(readInt(t0Out[1], t0Out[0]))
t1Out_v := float32(readInt(t1Out[1], t1Out[0]))
d.humiditySlope = (h1rH_v - h0rH_v) / (h1t0Out_v - h0t0Out_v)
d.humidityZero = h0rH_v - d.humiditySlope*h0t0Out_v
d.temperatureSlope = (t1degC_v - t0degC_v) / (t1Out_v - t0Out_v)
d.temperatureZero = t0degC_v - d.temperatureSlope*t0Out_v
}
// wait and trigger one shot in block update
func (d *Device) waitForOneShot(filter uint8) error {
data := []byte{0}
// check if the device is on
d.bus.ReadRegister(d.Address, HTS221_CTRL1_REG, data)
if data[0]&0x80 == 0 {
return errors.New("device is off, unable to query")
}
// wait until one shot (one conversion) is ready to go
data[0] = 1
for {
d.bus.ReadRegister(d.Address, HTS221_CTRL2_REG, data)
if data[0]&0x01 == 0 {
break
}
}
// trigger one shot
d.bus.WriteRegister(d.Address, HTS221_CTRL2_REG, []byte{0x01})
// wait until conversion completed
data[0] = 0
for {
d.bus.ReadRegister(d.Address, HTS221_STATUS_REG, data)
if data[0]&filter == filter {
break
}
}
return nil
}
func readUint(msb byte, lsb byte) uint16 {
return uint16(msb)<<8 | uint16(lsb)
}
func readInt(msb byte, lsb byte) int16 {
return int16(uint16(msb)<<8 | uint16(lsb))
}
+14
View File
@@ -0,0 +1,14 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package hts221
import "tinygo.org/x/drivers"
// Configure sets up the HTS221 device for communication.
func (d *Device) Configure() {
// read calibration data
d.calibration()
// activate device and use block data update mode
d.Power(true)
}
+25
View File
@@ -0,0 +1,25 @@
//go:build nano_33_ble
// +build nano_33_ble
package hts221
import (
"machine"
"time"
)
// Configure sets up the HTS221 device for communication.
func (d *Device) Configure() {
// Following lines are Nano 33 BLE specific, they have nothing to do with sensor per se
machine.HTS_PWR.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.HTS_PWR.High()
machine.I2C_PULLUP.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.I2C_PULLUP.High()
// Wait a moment
time.Sleep(10 * time.Millisecond)
// read calibration data
d.calibration()
// activate device and use block data update mode
d.Power(true)
}
+27
View File
@@ -0,0 +1,27 @@
package hts221
const (
// I2C address
HTS221_ADDRESS = 0x5F
// control/status registers
HTS221_WHO_AM_I_REG = 0x0F
HTS221_AV_CONF_REG = 0x10
HTS221_CTRL1_REG = 0x20
HTS221_CTRL2_REG = 0x21
HTS221_STATUS_REG = 0x27
HTS221_HUMID_OUT_REG = 0x28
HTS221_TEMP_OUT_REG = 0x2A
// calibration registers
HTS221_H0_rH_x2_REG = 0x30
HTS221_H1_rH_x2_REG = 0x31
HTS221_T0_degC_x8_REG = 0x32
HTS221_T1_degC_x8_REG = 0x33
HTS221_T1_T0_MSB_REG = 0x35
HTS221_H0_T0_OUT_REG = 0x36
HTS221_H1_T0_OUT_REG = 0x3A
HTS221_T0_OUT_REG = 0x3C
HTS221_T1_OUT_REG = 0x3E
)
+280
View File
@@ -0,0 +1,280 @@
package i2csoft
import (
"errors"
"machine"
)
// I2C is an I2C implementation by Software. Since it is implemented by
// software, it can be used with microcontrollers that do not have I2C
// function. This is not efficient but works around broken or missing drivers.
type I2C struct {
scl machine.Pin
sda machine.Pin
nack bool
baudrate uint32
}
// I2CConfig is used to store config info for I2C.
type I2CConfig struct {
Frequency uint32
SCL machine.Pin
SDA machine.Pin
}
var (
errSI2CAckExpected = errors.New("I2C error: expected ACK not NACK")
)
// New returns the i2csoft driver. For the arguments, specify the pins to be
// used as SCL and SDA. As I2C is implemented in software, any GPIO pin can be
// specified.
func New(sclPin, sdaPin machine.Pin) *I2C {
return &I2C{
scl: sclPin,
sda: sdaPin,
baudrate: 100e3,
}
}
// Configure is intended to setup the I2C interface.
func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz.
if config.Frequency != 0 {
i2c.SetBaudRate(config.Frequency)
}
// This exists for compatibility with machine.I2CConfig. SCL and SDA must
// be set at the same time. Because Pin(0) is sometimes set, it is not
// checked for 0.
if config.SCL != config.SDA {
i2c.scl = config.SCL
i2c.sda = config.SDA
}
// enable pins
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
i2c.sda.High()
i2c.scl.Configure(machine.PinConfig{Mode: machine.PinOutput})
i2c.scl.High()
return nil
}
// SetBaudRate sets the communication speed for the I2C.
func (i2c *I2C) SetBaudRate(br uint32) {
// At this time, the value of i2c.baudrate is ignored because it is fixed
// at 100 kHz. SetBaudrate() is exist for compatibility with machine.I2C.
i2c.baudrate = br
}
// Tx does a single I2C transaction at the specified address.
// It clocks out the given address, writes the bytes in w, reads back len(r)
// bytes and stores them in r, and generates a stop condition on the bus.
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
i2c.nack = false
if len(w) != 0 {
// send start/address for write
i2c.sendAddress(addr, true)
// wait until transmission complete
// ACK received (0: ACK, 1: NACK)
if i2c.nack {
i2c.signalStop()
return errSI2CAckExpected
}
// write data
for _, b := range w {
i2c.writeByte(b)
}
i2c.signalStop()
}
if len(r) != 0 {
// send start/address for read
i2c.sendAddress(addr, false)
// wait transmission complete
// ACK received (0: ACK, 1: NACK)
if i2c.nack {
i2c.signalStop()
return errSI2CAckExpected
}
// read first byte
r[0] = i2c.readByte()
for i := 1; i < len(r); i++ {
// Send an ACK
i2c.signalRead()
// Read data and send the ACK
r[i] = i2c.readByte()
}
// Send NACK to end transmission
i2c.sendNack()
i2c.signalStop()
}
return nil
}
// writeByte writes a single byte to the I2C bus.
func (i2c *I2C) writeByte(data byte) {
// Send data byte
i2c.scl.Low()
i2c.sda.High()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
i2c.wait()
for i := 0; i < 8; i++ {
i2c.scl.Low()
if ((data >> (7 - i)) & 1) == 1 {
i2c.sda.High()
} else {
i2c.sda.Low()
}
i2c.wait()
i2c.wait()
i2c.scl.High()
i2c.wait()
i2c.wait()
}
i2c.scl.Low()
i2c.wait()
i2c.wait()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinInput})
i2c.scl.High()
i2c.wait()
i2c.nack = i2c.sda.Get()
i2c.wait()
// wait until transmission successful
}
// sendAddress sends the address and start signal
func (i2c *I2C) sendAddress(address uint16, write bool) {
data := (address << 1)
if !write {
data |= 1 // set read flag
}
i2c.scl.High()
i2c.sda.Low()
i2c.wait()
i2c.wait()
for i := 0; i < 8; i++ {
i2c.scl.Low()
if ((data >> (7 - i)) & 1) == 1 {
i2c.sda.High()
} else {
i2c.sda.Low()
}
i2c.wait()
i2c.wait()
i2c.scl.High()
i2c.wait()
i2c.wait()
}
i2c.scl.Low()
i2c.wait()
i2c.wait()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinInput})
i2c.scl.High()
i2c.wait()
i2c.nack = i2c.sda.Get()
i2c.wait()
// wait until bus ready
}
func (i2c *I2C) signalStop() {
i2c.scl.Low()
i2c.sda.Low()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
i2c.wait()
i2c.wait()
i2c.scl.High()
i2c.wait()
i2c.wait()
i2c.sda.High()
i2c.wait()
i2c.wait()
}
func (i2c *I2C) signalRead() {
i2c.wait()
i2c.wait()
i2c.scl.Low()
i2c.sda.Low()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
i2c.wait()
i2c.wait()
i2c.scl.High()
i2c.wait()
i2c.wait()
}
func (i2c *I2C) readByte() byte {
var data byte
for i := 0; i < 8; i++ {
i2c.scl.Low()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinInput})
i2c.wait()
i2c.wait()
i2c.scl.High()
if i2c.sda.Get() {
data |= 1 << (7 - i)
}
i2c.wait()
i2c.wait()
}
return data
}
func (i2c *I2C) sendNack() {
i2c.wait()
i2c.wait()
i2c.scl.Low()
i2c.sda.High()
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
i2c.wait()
i2c.wait()
i2c.scl.High()
i2c.wait()
i2c.wait()
}
// WriteRegister transmits first the register and then the data to the
// peripheral device.
//
// Many I2C-compatible devices are organized in terms of registers. This method
// is a shortcut to easily write to such registers. Also, it only works for
// devices with 7-bit addresses, which is the vast majority.
func (i2c *I2C) WriteRegister(address uint8, register uint8, data []byte) error {
buf := make([]uint8, len(data)+1)
buf[0] = register
copy(buf[1:], data)
return i2c.Tx(uint16(address), buf, nil)
}
// ReadRegister transmits the register, restarts the connection as a read
// operation, and reads the response.
//
// Many I2C-compatible devices are organized in terms of registers. This method
// is a shortcut to easily read such registers. Also, it only works for devices
// with 7-bit addresses, which is the vast majority.
func (i2c *I2C) ReadRegister(address uint8, register uint8, data []byte) error {
return i2c.Tx(uint16(address), []byte{register}, data)
}
+17
View File
@@ -0,0 +1,17 @@
//go:build atsamd51 || atsame5x
// +build atsamd51 atsame5x
package i2csoft
import (
"device"
)
// wait waits for half the time of the SCL operation interval. It is set to
// about 100 kHz.
func (i2c *I2C) wait() {
wait := 20
for i := 0; i < wait; i++ {
device.Asm(`nop`)
}
}
+17
View File
@@ -0,0 +1,17 @@
//go:build esp32
// +build esp32
package i2csoft
import (
"device"
)
// wait waits for half the time of the SCL operation interval. It is set to
// about 100 kHz.
func (i2c *I2C) wait() {
wait := 60
for i := 0; i < wait; i++ {
device.Asm(`nop`)
}
}
+17
View File
@@ -0,0 +1,17 @@
//go:build nrf52840
// +build nrf52840
package i2csoft
import (
"device"
)
// wait waits for half the time of the SCL operation interval. It is set to
// about 100 kHz.
func (i2c *I2C) wait() {
wait := 26
for i := 0; i < wait; i++ {
device.Asm(`nop`)
}
}
+16
View File
@@ -0,0 +1,16 @@
//go:build !esp32 && !atsamd51 && !atsame5x && !stm32f4 && !rp2040 && !nrf52840
// +build !esp32,!atsamd51,!atsame5x,!stm32f4,!rp2040,!nrf52840
package i2csoft
import (
"device"
)
// wait waits for half the time of the SCL operation interval.
func (i2c *I2C) wait() {
wait := 20
for i := 0; i < wait; i++ {
device.Asm(`nop`)
}
}
+17
View File
@@ -0,0 +1,17 @@
//go:build rp2040
// +build rp2040
package i2csoft
import (
"device"
)
// wait waits for half the time of the SCL operation interval. It is set to
// about 100 kHz.
func (i2c *I2C) wait() {
wait := 50
for i := 0; i < wait; i++ {
device.Asm(`nop`)
}
}

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