mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-17 21:23:58 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dbff576c9e | |||
| f0a260be66 | |||
| 06e298c514 | |||
| f2f470973d | |||
| 448598cbf8 | |||
| ec98f2dc2c | |||
| 2476cd7bd8 | |||
| 01fed475e1 | |||
| edfdd4e09e | |||
| 5e54f08605 | |||
| 880b958d64 | |||
| 24db8b4e2c | |||
| 6df9247f92 | |||
| 56fb346438 | |||
| 3d279d4d25 | |||
| 4a336f674c | |||
| 2d32995f6a | |||
| 9a98d1be55 | |||
| 02e4548966 | |||
| 45dce188f5 | |||
| b3c0315a09 | |||
| 0ced12683c | |||
| b4eb406a43 | |||
| 10bd48c39d | |||
| ad3ef92cfe | |||
| f7dce6ae22 | |||
| a15f2167cc | |||
| 5d5378a47c | |||
| 3ceb688663 | |||
| 941c1c9057 | |||
| d8c813d515 | |||
| 905fc6fce3 | |||
| 80913d5fe7 | |||
| b6c750ccd1 | |||
| 43899e1330 | |||
| 45c68ef0fc | |||
| 025a66655f | |||
| 121e8147f7 | |||
| b48bc5ac5d | |||
| 0d40c99d1f | |||
| bee7422c3a | |||
| 43099c5d5f | |||
| 0f9b9d873b | |||
| 114e24870e | |||
| b33c84ff78 | |||
| 966210f1b0 |
@@ -1,3 +1,71 @@
|
|||||||
|
0.20.0
|
||||||
|
---
|
||||||
|
- **new devices**
|
||||||
|
- irremote: Add basic infra-red driver
|
||||||
|
- IS31FL3731: add driver for IS31FL3731 matrix LED driver (#370)
|
||||||
|
- l3gd20: add gyro driver
|
||||||
|
- SSD1289: Driver for SSD1289 LCD
|
||||||
|
|
||||||
|
- **enhancements**
|
||||||
|
- **ili9341**
|
||||||
|
- add support for atsame5x
|
||||||
|
- added Feather board support to InitDisplay()
|
||||||
|
- avoid heap allocations
|
||||||
|
- **lps22hb**
|
||||||
|
- pin rename, sync with main repo
|
||||||
|
- **lsmXXX**
|
||||||
|
- unified, error handling, memory management
|
||||||
|
- **max7xx**
|
||||||
|
- Add a SetIntensity() function to max7xx driver and example
|
||||||
|
- **vl53l1x**
|
||||||
|
- Add functions for setting 'region of interest'
|
||||||
|
- Fix switch-case semantics
|
||||||
|
- **ws2812**
|
||||||
|
- add support for m5stamp-c3
|
||||||
|
- convert AVR assembly to C inline assembly
|
||||||
|
- support high-MHz ARMv6M chips like the RP2040
|
||||||
|
- write inline assembly using C instead of Go
|
||||||
|
|
||||||
|
- **bugfixes**
|
||||||
|
- **dht**
|
||||||
|
- fix error check in example
|
||||||
|
- fix humidity and temperature extraction for DHT22 (#358)
|
||||||
|
- **esp8266**
|
||||||
|
- fix ConnectToAccessPoint timeout args
|
||||||
|
- **image**
|
||||||
|
- fix interface
|
||||||
|
- **pca9685**
|
||||||
|
- add buffered one shot write
|
||||||
|
- fix on=0 bug
|
||||||
|
- **wifinina**
|
||||||
|
- correct sendParamStr to handle empty strings, such as when connecting to an unsecured access point
|
||||||
|
|
||||||
|
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
|
0.18.0
|
||||||
---
|
---
|
||||||
- **new devices**
|
- **new devices**
|
||||||
|
|||||||
@@ -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
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ smoke-test:
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
|
tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
|
||||||
@@ -117,6 +119,8 @@ smoke-test:
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
|
||||||
@md5sum ./build/test.hex
|
@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
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
|
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
|
||||||
@@ -155,6 +159,10 @@ smoke-test:
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
|
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.bin -target=m5stamp-c3 ./examples/ws2812
|
||||||
|
@md5sum ./build/test.bin
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/is31fl3731/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
ifneq ($(AVR), 0)
|
ifneq ($(AVR), 0)
|
||||||
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/ws2812
|
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/ws2812
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
@@ -187,8 +195,8 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
|
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go
|
# tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go
|
||||||
@md5sum ./build/test.hex
|
# @md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
|
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clkout/
|
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clkout/
|
||||||
@@ -215,12 +223,25 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
|
tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
|
||||||
|
@md5sum ./build/test.uf2
|
||||||
|
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/basic/
|
||||||
|
@md5sum ./build/test.elf
|
||||||
|
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/touchpaint/
|
||||||
|
@md5sum ./build/test.elf
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/sx126x/lora_rxtx/
|
||||||
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/ssd1289/main.go
|
||||||
|
@md5sum ./build/test.uf2
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=pico ./examples/irremote/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
|
|
||||||
DRIVERS = $(wildcard */)
|
DRIVERS = $(wildcard */)
|
||||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||||
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
|
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 \
|
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x keypad4x4 max72xx p1am tone tm1637 \
|
||||||
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192
|
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192 xpt2046 \
|
||||||
|
ft6336 sx126x ssd1289 irremote
|
||||||
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
||||||
|
|
||||||
unit-test:
|
unit-test:
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func main() {
|
|||||||
|
|
||||||
## Currently supported devices
|
## Currently supported devices
|
||||||
|
|
||||||
The following 74 devices are supported.
|
The following 78 devices are supported.
|
||||||
|
|
||||||
| Device Name | Interface Type |
|
| Device Name | Interface Type |
|
||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
@@ -78,6 +78,7 @@ The following 74 devices are supported.
|
|||||||
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
|
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
|
||||||
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
|
||||||
@@ -86,6 +87,8 @@ The following 74 devices are supported.
|
|||||||
| [software I2C driver](https://www.ti.com/lit/an/slva704/slva704.pdf) | GPIO |
|
| [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 |
|
| [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 |
|
| [INA260 Volt/Amp/Power meter](https://www.ti.com/lit/ds/symlink/ina260.pdf) | I2C |
|
||||||
|
| [Infrared remote control](https://en.wikipedia.org/wiki/Consumer_IR) | GPIO |
|
||||||
|
| [IS31FL3731 matrix LED driver](https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf) | I2C |
|
||||||
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
|
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
|
||||||
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
|
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
|
||||||
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
||||||
@@ -114,6 +117,7 @@ The following 74 devices are supported.
|
|||||||
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
|
| [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 |
|
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
|
||||||
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
|
| [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 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 |
|
| [SPI SDCARD/MMC](https://en.wikipedia.org/wiki/SD_card) | SPI |
|
||||||
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
|
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
|
||||||
@@ -131,6 +135,9 @@ The following 74 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 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 |
|
| [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 |
|
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
|
||||||
|
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
|
||||||
|
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-transceiv-ers/sx1261) | SPI |
|
||||||
|
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
+53
-46
@@ -57,6 +57,14 @@ type enableConfig struct {
|
|||||||
PON 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.
|
// Connected returns whether APDS-9960 has been found.
|
||||||
// It does a "who am I" request and checks the response.
|
// It does a "who am I" request and checks the response.
|
||||||
func (d *Device) Connected() bool {
|
func (d *Device) Connected() bool {
|
||||||
@@ -65,52 +73,6 @@ func (d *Device) Connected() bool {
|
|||||||
return data[0] == 0xAB
|
return data[0] == 0xAB
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure sets up the APDS-9960 device.
|
|
||||||
func (d *Device) Configure(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMode returns current engine mode
|
// GetMode returns current engine mode
|
||||||
func (d *Device) GetMode() uint8 {
|
func (d *Device) GetMode() uint8 {
|
||||||
return d.mode
|
return d.mode
|
||||||
@@ -353,6 +315,51 @@ func (d *Device) ReadGesture() (gesture int32) {
|
|||||||
|
|
||||||
// private functions
|
// 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) {
|
func (d *Device) enable(cfg enableConfig) {
|
||||||
var gen, pien, aien, wen, pen, aen, pon uint8
|
var gen, pien, aien, wen, pen, aen, pon uint8
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ package apds9960
|
|||||||
|
|
||||||
import "tinygo.org/x/drivers"
|
import "tinygo.org/x/drivers"
|
||||||
|
|
||||||
// New creates a new APDS-9960 connection. The I2C bus must already be
|
// Configure sets up the APDS-9960 device.
|
||||||
// configured.
|
func (d *Device) Configure(cfg Configuration) {
|
||||||
//
|
// configure device
|
||||||
// This function only creates the Device object, it does not touch the device.
|
d.configureDevice(cfg)
|
||||||
func New(bus drivers.I2C) Device {
|
|
||||||
return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,24 +6,19 @@ package apds9960
|
|||||||
import (
|
import (
|
||||||
"machine"
|
"machine"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/drivers"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// New creates a new APDS-9960 connection. The I2C bus must already be
|
// Configure sets up the APDS-9960 device.
|
||||||
// configured.
|
func (d *Device) Configure(cfg Configuration) {
|
||||||
//
|
|
||||||
// This function only creates the Device object, it does not touch the device.
|
|
||||||
func New(bus drivers.I2C) Device {
|
|
||||||
// turn on internal power pin (machine.P0_22) and I2C1 pullups power pin (machine.P1_00)
|
|
||||||
// and wait a moment.
|
|
||||||
ENV := machine.P0_22
|
|
||||||
ENV.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
||||||
ENV.High()
|
|
||||||
R := machine.P1_00
|
|
||||||
R.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
||||||
R.High()
|
|
||||||
time.Sleep(time.Millisecond * 10)
|
|
||||||
|
|
||||||
return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE}
|
// 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)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-27
@@ -1,3 +1,6 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
// +build tinygo
|
||||||
|
|
||||||
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
|
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
|
||||||
//
|
//
|
||||||
// [1] Datasheet DHT11: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
|
// [1] Datasheet DHT11: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
|
||||||
@@ -7,34 +10,10 @@
|
|||||||
package dht // import "tinygo.org/x/drivers/dht"
|
package dht // import "tinygo.org/x/drivers/dht"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"machine"
|
"machine"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// enum type for device type
|
|
||||||
type DeviceType uint8
|
|
||||||
|
|
||||||
// DeviceType specific parsing of information received from the sensor
|
|
||||||
func (d DeviceType) extractData(buf []byte) (temp int16, hum uint16) {
|
|
||||||
if d == DHT11 {
|
|
||||||
temp = int16(buf[2])
|
|
||||||
if buf[3]&0x80 > 0 {
|
|
||||||
temp = -1 - temp
|
|
||||||
}
|
|
||||||
temp *= 10
|
|
||||||
temp += int16(buf[3] & 0x0f)
|
|
||||||
hum = 10*uint16(buf[0]) + uint16(buf[1])
|
|
||||||
} else {
|
|
||||||
hum = binary.LittleEndian.Uint16(buf[0:2])
|
|
||||||
temp = int16(buf[3])<<8 + int16(buf[2]&0x7f)
|
|
||||||
if buf[2]&0x80 > 0 {
|
|
||||||
temp = -temp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Celsius and Fahrenheit temperature scales
|
// Celsius and Fahrenheit temperature scales
|
||||||
type TemperatureScale uint8
|
type TemperatureScale uint8
|
||||||
|
|
||||||
@@ -54,9 +33,6 @@ const (
|
|||||||
startTimeout = time.Millisecond * 200
|
startTimeout = time.Millisecond * 200
|
||||||
startingLow = time.Millisecond * 20
|
startingLow = time.Millisecond * 20
|
||||||
|
|
||||||
DHT11 DeviceType = iota
|
|
||||||
DHT22
|
|
||||||
|
|
||||||
C TemperatureScale = iota
|
C TemperatureScale = iota
|
||||||
F
|
F
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package dht
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeviceType is the enum type for device type
|
||||||
|
type DeviceType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
DHT11 DeviceType = iota
|
||||||
|
DHT22
|
||||||
|
)
|
||||||
|
|
||||||
|
// extractData parses information received from the sensor.
|
||||||
|
// The 2 first buffers are for the humidity and
|
||||||
|
// the 2 following corresponds to the temperature.
|
||||||
|
func (d DeviceType) extractData(buf []byte) (temp int16, hum uint16) {
|
||||||
|
switch d {
|
||||||
|
case DHT11:
|
||||||
|
hum = 10*uint16(buf[0]) + uint16(buf[1])
|
||||||
|
temp = int16(buf[2])
|
||||||
|
if buf[3]&0x80 > 0 {
|
||||||
|
temp = -1 - temp
|
||||||
|
}
|
||||||
|
temp *= 10
|
||||||
|
temp += int16(buf[3] & 0x0f)
|
||||||
|
case DHT22:
|
||||||
|
hum = binary.BigEndian.Uint16(buf[0:2])
|
||||||
|
temp = int16(buf[2]&0x7f)<<8 + int16(buf[3])
|
||||||
|
// the first bit corresponds to the sign bit
|
||||||
|
if buf[2]&0x80 > 0 {
|
||||||
|
temp = -temp
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// keeping this for retro-compatibility but not tested
|
||||||
|
hum = binary.LittleEndian.Uint16(buf[0:2])
|
||||||
|
temp = int16(buf[3])<<8 + int16(buf[2]&0x7f)
|
||||||
|
if buf[2]&0x80 > 0 {
|
||||||
|
temp = -temp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package dht
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDeviceType_extractData(t *testing.T) {
|
||||||
|
bitStr := "0000001010001100000000010101111111101110"
|
||||||
|
buf := bitStringToBytes(bitStr)
|
||||||
|
|
||||||
|
tt := []struct {
|
||||||
|
name string
|
||||||
|
d DeviceType
|
||||||
|
buf []byte
|
||||||
|
wantTemp int16
|
||||||
|
wantHum uint16
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// temp = 35.1C hum = 65.2%
|
||||||
|
name: "DHT22", d: DHT22, buf: buf, wantTemp: 351, wantHum: 652,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tt {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
gotTemp, gotHum := tc.d.extractData(tc.buf)
|
||||||
|
if gotTemp != tc.wantTemp {
|
||||||
|
t.Errorf("extractData() gotTemp = %v, want %v", gotTemp, tc.wantTemp)
|
||||||
|
}
|
||||||
|
if gotHum != tc.wantHum {
|
||||||
|
t.Errorf("extractData() gotHum = %v, want %v", gotHum, tc.wantHum)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bitStringToBytes(s string) []byte {
|
||||||
|
b := make([]byte, (len(s)+(8-1))/8)
|
||||||
|
for i, r := range s {
|
||||||
|
if r < '0' || r > '1' {
|
||||||
|
panic("not in range")
|
||||||
|
}
|
||||||
|
b[i>>3] |= byte(r-'0') << uint(7-i&7)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
// +build tinygo
|
||||||
|
|
||||||
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
|
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
|
||||||
//
|
//
|
||||||
// [1] Datasheet DHT11: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
|
// [1] Datasheet DHT11: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
// +build tinygo
|
||||||
|
|
||||||
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
|
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
|
||||||
//
|
//
|
||||||
// [1] Datasheet DHT11: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
|
// [1] Datasheet DHT11: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
// +build tinygo
|
||||||
|
|
||||||
package dht // import "tinygo.org/x/drivers/dht"
|
package dht // import "tinygo.org/x/drivers/dht"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetWifiMode(WifiModeClient)
|
||||||
|
return d.ConnectToAP(ssid, pass, int(timeout.Seconds()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) Disconnect() error {
|
||||||
|
return d.DisconnectFromAP()
|
||||||
|
}
|
||||||
@@ -9,21 +9,22 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// use Nano 33 BLE Sense's internal I2C bus
|
||||||
machine.I2C1.Configure(machine.I2CConfig{
|
machine.I2C1.Configure(machine.I2CConfig{
|
||||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
SCL: machine.SCL1_PIN,
|
||||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
SDA: machine.SDA1_PIN,
|
||||||
Frequency: machine.TWI_FREQ_400KHZ,
|
Frequency: machine.TWI_FREQ_400KHZ,
|
||||||
})
|
})
|
||||||
|
|
||||||
sensor := apds9960.New(machine.I2C1)
|
sensor := apds9960.New(machine.I2C1)
|
||||||
|
|
||||||
|
sensor.Configure(apds9960.Configuration{}) // use default settings
|
||||||
|
|
||||||
if !sensor.Connected() {
|
if !sensor.Connected() {
|
||||||
println("APDS-9960 not connected!")
|
println("APDS-9960 not connected!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor.Configure(apds9960.Configuration{}) // use default settings
|
|
||||||
|
|
||||||
sensor.EnableColor() // enable color engine
|
sensor.EnableColor() // enable color engine
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -9,21 +9,22 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// use Nano 33 BLE Sense's internal I2C bus
|
||||||
machine.I2C1.Configure(machine.I2CConfig{
|
machine.I2C1.Configure(machine.I2CConfig{
|
||||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
SCL: machine.SCL1_PIN,
|
||||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
SDA: machine.SDA1_PIN,
|
||||||
Frequency: machine.TWI_FREQ_400KHZ,
|
Frequency: machine.TWI_FREQ_400KHZ,
|
||||||
})
|
})
|
||||||
|
|
||||||
sensor := apds9960.New(machine.I2C1)
|
sensor := apds9960.New(machine.I2C1)
|
||||||
|
|
||||||
|
sensor.Configure(apds9960.Configuration{}) // use default settings
|
||||||
|
|
||||||
if !sensor.Connected() {
|
if !sensor.Connected() {
|
||||||
println("APDS-9960 not connected!")
|
println("APDS-9960 not connected!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor.Configure(apds9960.Configuration{}) // use default settings
|
|
||||||
|
|
||||||
sensor.EnableGesture() // enable gesture engine
|
sensor.EnableGesture() // enable gesture engine
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -34,7 +35,7 @@ func main() {
|
|||||||
gesture := sensor.ReadGesture()
|
gesture := sensor.ReadGesture()
|
||||||
print("Detected gesture: ")
|
print("Detected gesture: ")
|
||||||
switch gesture {
|
switch gesture {
|
||||||
case apds9960.GESTURE_UP:
|
case apds9960.GESTURE_UP: // the nRF52 chip is "up"
|
||||||
println("Up")
|
println("Up")
|
||||||
case apds9960.GESTURE_DOWN:
|
case apds9960.GESTURE_DOWN:
|
||||||
println("Down")
|
println("Down")
|
||||||
|
|||||||
@@ -9,21 +9,23 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// use Nano 33 BLE Sense's internal I2C bus
|
||||||
machine.I2C1.Configure(machine.I2CConfig{
|
machine.I2C1.Configure(machine.I2CConfig{
|
||||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
SCL: machine.SCL1_PIN,
|
||||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
SDA: machine.SDA1_PIN,
|
||||||
Frequency: machine.TWI_FREQ_400KHZ,
|
Frequency: machine.TWI_FREQ_400KHZ,
|
||||||
})
|
})
|
||||||
|
|
||||||
sensor := apds9960.New(machine.I2C1)
|
sensor := apds9960.New(machine.I2C1)
|
||||||
|
|
||||||
|
// use default settings
|
||||||
|
sensor.Configure(apds9960.Configuration{})
|
||||||
|
|
||||||
if !sensor.Connected() {
|
if !sensor.Connected() {
|
||||||
println("APDS-9960 not connected!")
|
println("APDS-9960 not connected!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor.Configure(apds9960.Configuration{}) // use default settings
|
|
||||||
|
|
||||||
sensor.EnableProximity() // enable proximity engine
|
sensor.EnableProximity() // enable proximity engine
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func main() {
|
|||||||
dhtSensor := dht.New(pin, dht.DHT11)
|
dhtSensor := dht.New(pin, dht.DHT11)
|
||||||
for {
|
for {
|
||||||
temp, hum, err := dhtSensor.Measurements()
|
temp, hum, err := dhtSensor.Measurements()
|
||||||
if err != nil {
|
if err == nil {
|
||||||
fmt.Printf("Temperature: %02d.%d°C, Humidity: %02d.%d%%\n", temp/10, temp%10, hum/10, hum%10)
|
fmt.Printf("Temperature: %02d.%d°C, Humidity: %02d.%d%%\n", temp/10, temp%10, hum/10, hum%10)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Could not take measurements from the sensor: %s\n", err.Error())
|
fmt.Printf("Could not take measurements from the sensor: %s\n", err.Error())
|
||||||
|
|||||||
@@ -113,8 +113,9 @@ func connectToESP() bool {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
println("Connecting to wifi network '" + ssid + "'")
|
println("Connecting to wifi network '" + ssid + "'")
|
||||||
|
|
||||||
adaptor.SetWifiMode(espat.WifiModeClient)
|
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
|
||||||
adaptor.ConnectToAP(ssid, pass, 10)
|
failMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
ip, err := adaptor.GetClientIP()
|
ip, err := adaptor.GetClientIP()
|
||||||
|
|||||||
@@ -99,8 +99,9 @@ func connectToESP() bool {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
println("Connecting to wifi network '" + ssid + "'")
|
println("Connecting to wifi network '" + ssid + "'")
|
||||||
|
|
||||||
adaptor.SetWifiMode(espat.WifiModeClient)
|
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
|
||||||
adaptor.ConnectToAP(ssid, pass, 10)
|
failMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
ip, err := adaptor.GetClientIP()
|
ip, err := adaptor.GetClientIP()
|
||||||
|
|||||||
@@ -88,8 +88,9 @@ func connectToESP() bool {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
println("Connecting to wifi network '" + ssid + "'")
|
println("Connecting to wifi network '" + ssid + "'")
|
||||||
|
|
||||||
adaptor.SetWifiMode(espat.WifiModeClient)
|
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
|
||||||
adaptor.ConnectToAP(ssid, pass, 10)
|
failMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
ip, err := adaptor.GetClientIP()
|
ip, err := adaptor.GetClientIP()
|
||||||
|
|||||||
@@ -108,8 +108,9 @@ func connectToESP() bool {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
println("Connecting to wifi network '" + ssid + "'")
|
println("Connecting to wifi network '" + ssid + "'")
|
||||||
|
|
||||||
adaptor.SetWifiMode(espat.WifiModeClient)
|
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
|
||||||
adaptor.ConnectToAP(ssid, pass, 10)
|
failMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
ip, err := adaptor.GetClientIP()
|
ip, err := adaptor.GetClientIP()
|
||||||
|
|||||||
@@ -129,8 +129,9 @@ func connectToESP() bool {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
println("Connecting to wifi network '" + ssid + "'")
|
println("Connecting to wifi network '" + ssid + "'")
|
||||||
|
|
||||||
adaptor.SetWifiMode(espat.WifiModeClient)
|
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
|
||||||
adaptor.ConnectToAP(ssid, pass, 10)
|
failMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
ip, err := adaptor.GetClientIP()
|
ip, err := adaptor.GetClientIP()
|
||||||
|
|||||||
@@ -91,8 +91,9 @@ func connectToESP() bool {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
println("Connecting to wifi network '" + ssid + "'")
|
println("Connecting to wifi network '" + ssid + "'")
|
||||||
|
|
||||||
adaptor.SetWifiMode(espat.WifiModeClient)
|
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
|
||||||
adaptor.ConnectToAP(ssid, pass, 10)
|
failMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
ip, err := adaptor.GetClientIP()
|
ip, err := adaptor.GetClientIP()
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,28 +9,27 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// use Nano 33 BLE Sense's internal I2C bus
|
||||||
machine.I2C1.Configure(machine.I2CConfig{
|
machine.I2C1.Configure(machine.I2CConfig{
|
||||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
SCL: machine.SCL1_PIN,
|
||||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
SDA: machine.SDA1_PIN,
|
||||||
Frequency: machine.TWI_FREQ_400KHZ,
|
Frequency: machine.TWI_FREQ_400KHZ,
|
||||||
})
|
})
|
||||||
|
|
||||||
sensor := hts221.New(machine.I2C1)
|
sensor := hts221.New(machine.I2C1)
|
||||||
|
|
||||||
|
sensor.Configure() // power on and calibrate
|
||||||
|
|
||||||
if !sensor.Connected() {
|
if !sensor.Connected() {
|
||||||
println("HTS221 not connected!")
|
println("HTS221 not connected!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor.Configure() // power on and calibrate
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
||||||
h, _ := sensor.ReadHumidity()
|
h, _ := sensor.ReadHumidity()
|
||||||
t, _ := sensor.ReadTemperature()
|
t, _ := sensor.ReadTemperature()
|
||||||
println("h =", float32(h)/100.0, "% / t =", float32(t)/1000.0, "*C")
|
println("h =", float32(h)/100.0, "% / t =", float32(t)/1000.0, "*C")
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
//go:build feather_m0 || feather_m4 || feather_m4_can || feather_nrf52840 || feather_nrf52840_sense || feather_stm32f405 || feather_rp2040
|
||||||
|
// +build feather_m0 feather_m4 feather_m4_can feather_nrf52840 feather_nrf52840_sense feather_stm32f405 feather_rp2040
|
||||||
|
|
||||||
|
package initdisplay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/ili9341"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitDisplay() *ili9341.Device {
|
||||||
|
machine.D5.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
machine.D6.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
|
||||||
|
machine.SPI0.Configure(machine.SPIConfig{
|
||||||
|
SCK: machine.SPI0_SCK_PIN,
|
||||||
|
SDO: machine.SPI0_SDO_PIN,
|
||||||
|
SDI: machine.SPI0_SDI_PIN,
|
||||||
|
Frequency: 40000000,
|
||||||
|
})
|
||||||
|
|
||||||
|
// configure backlight
|
||||||
|
backlight := machine.D9
|
||||||
|
backlight.Configure(machine.PinConfig{machine.PinOutput})
|
||||||
|
|
||||||
|
display := ili9341.NewSPI(
|
||||||
|
machine.SPI0,
|
||||||
|
machine.D10, // LCD_DC,
|
||||||
|
machine.D11, // LCD_SS_PIN,
|
||||||
|
machine.D12, // LCD_RESET,
|
||||||
|
)
|
||||||
|
|
||||||
|
// configure display
|
||||||
|
display.Configure(ili9341.Config{})
|
||||||
|
|
||||||
|
backlight.High()
|
||||||
|
|
||||||
|
display.SetRotation(ili9341.Rotation270)
|
||||||
|
|
||||||
|
return display
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -72,7 +72,8 @@ func drawPng(display *ili9341.Device) error {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return png.Decode(p)
|
_, err := png.Decode(p)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawJpeg(display *ili9341.Device) error {
|
func drawJpeg(display *ili9341.Device) error {
|
||||||
@@ -84,7 +85,8 @@ func drawJpeg(display *ili9341.Device) error {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return jpeg.Decode(p)
|
_, err := jpeg.Decode(p)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorMessage(err error) {
|
func errorMessage(err error) {
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/irremote"
|
||||||
|
)
|
||||||
|
|
||||||
|
var irCmdButtons = map[uint16]string{
|
||||||
|
0xA2: "POWER",
|
||||||
|
0xE2: "FUNC/STOP",
|
||||||
|
0x62: "VOL+",
|
||||||
|
0x22: "FAST BACK",
|
||||||
|
0x02: "PAUSE",
|
||||||
|
0xC2: "FAST FORWARD",
|
||||||
|
0xE0: "DOWN",
|
||||||
|
0xA8: "VOL-",
|
||||||
|
0x90: "UP",
|
||||||
|
0x98: "EQ",
|
||||||
|
0xB0: "ST/REPT",
|
||||||
|
0x68: "0",
|
||||||
|
0x30: "1",
|
||||||
|
0x18: "2",
|
||||||
|
0x7A: "3",
|
||||||
|
0x10: "4",
|
||||||
|
0x38: "5",
|
||||||
|
0x5A: "6",
|
||||||
|
0x42: "7",
|
||||||
|
0x4A: "8",
|
||||||
|
0x52: "9",
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
pinIRIn = machine.GP26
|
||||||
|
ir irremote.ReceiverDevice
|
||||||
|
)
|
||||||
|
|
||||||
|
func setupPins() {
|
||||||
|
ir = irremote.NewReceiver(pinIRIn)
|
||||||
|
ir.Configure()
|
||||||
|
}
|
||||||
|
|
||||||
|
func irCallback(data irremote.Data) {
|
||||||
|
msg := "Command: " + irCmdButtons[data.Command]
|
||||||
|
if data.Flags&irremote.DataFlagIsRepeat != 0 {
|
||||||
|
msg = msg + " (REPEAT)"
|
||||||
|
}
|
||||||
|
println(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
setupPins()
|
||||||
|
ir.SetCommandHandler(irCallback)
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Millisecond * 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"machine"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/is31fl3731"
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2CAddress -- address of led matrix
|
||||||
|
var I2CAddress uint8 = is31fl3731.I2C_ADDRESS_74
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bus := machine.I2C0
|
||||||
|
err := bus.Configure(machine.I2CConfig{})
|
||||||
|
if err != nil {
|
||||||
|
println("could not configure I2C:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create driver for Adafruit 15x7 CharliePlex LED Matrix FeatherWing
|
||||||
|
// (CharlieWing): https://www.adafruit.com/product/3163
|
||||||
|
ledMatrix := is31fl3731.NewAdafruitCharlieWing15x7(bus, I2CAddress)
|
||||||
|
|
||||||
|
err = ledMatrix.Configure()
|
||||||
|
if err != nil {
|
||||||
|
println("could not configure is31fl3731 driver:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the whole matrix on the frame #0 (visible by default)
|
||||||
|
ledMatrix.Fill(is31fl3731.FRAME_0, uint8(3))
|
||||||
|
|
||||||
|
// Draw couple pixels on the frame #1 (not visible yet)
|
||||||
|
ledMatrix.DrawPixelXY(is31fl3731.FRAME_1, uint8(0), uint8(0), uint8(10))
|
||||||
|
ledMatrix.DrawPixelXY(is31fl3731.FRAME_1, uint8(14), uint8(6), uint8(10))
|
||||||
|
|
||||||
|
// There are 8 frames available, it's a good idea to draw on an invisible
|
||||||
|
// frame and then switch to that frame to reduce flickering. Switch between
|
||||||
|
// frame #0 and #1 in a loop to show animation:
|
||||||
|
for {
|
||||||
|
println("show frame #0...")
|
||||||
|
ledMatrix.SetActiveFrame(is31fl3731.FRAME_0)
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
|
||||||
|
println("show frame #1...")
|
||||||
|
ledMatrix.SetActiveFrame(is31fl3731.FRAME_1)
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/l3gd20"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
const (
|
||||||
|
// Default address on most breakout boards.
|
||||||
|
pcaAddr = 0x40
|
||||||
|
)
|
||||||
|
|
||||||
|
bus := machine.I2C0
|
||||||
|
|
||||||
|
err := bus.Configure(machine.I2CConfig{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
gyro := l3gd20.NewI2C(bus, 105)
|
||||||
|
err = gyro.Configure(l3gd20.Config{Range: l3gd20.Range_250})
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var x, y, z int32
|
||||||
|
for {
|
||||||
|
err = gyro.Update()
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
}
|
||||||
|
x, y, z = gyro.AngularVelocity()
|
||||||
|
println(x, y, z)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,29 +9,27 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// use Nano 33 BLE Sense's internal I2C bus
|
||||||
machine.I2C1.Configure(machine.I2CConfig{
|
machine.I2C1.Configure(machine.I2CConfig{
|
||||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
SCL: machine.SCL1_PIN,
|
||||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
SDA: machine.SDA1_PIN,
|
||||||
Frequency: machine.TWI_FREQ_400KHZ,
|
Frequency: machine.TWI_FREQ_400KHZ,
|
||||||
})
|
})
|
||||||
|
|
||||||
sensor := lps22hb.New(machine.I2C1)
|
sensor := lps22hb.New(machine.I2C1)
|
||||||
|
sensor.Configure()
|
||||||
|
|
||||||
if !sensor.Connected() {
|
if !sensor.Connected() {
|
||||||
println("LPS22HB not connected!")
|
println("LPS22HB not connected!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor.Configure()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
||||||
p, _ := sensor.ReadPressure()
|
p, _ := sensor.ReadPressure()
|
||||||
t, _ := sensor.ReadTemperature()
|
t, _ := sensor.ReadTemperature()
|
||||||
println("p =", float32(p)/1000.0, "hPa / t =", float32(t)/1000.0, "*C")
|
println("p =", float32(p)/1000.0, "hPa / t =", float32(t)/1000.0, "*C")
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
// note: the device would power down itself after each query
|
// note: the device would power down itself after each query
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-17
@@ -3,37 +3,62 @@ package main
|
|||||||
import (
|
import (
|
||||||
"machine"
|
"machine"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/drivers/lsm303agr"
|
"tinygo.org/x/drivers/lsm303agr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
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{})
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
accel_mag := lsm303agr.New(machine.I2C0)
|
|
||||||
|
|
||||||
if !accel_mag.Connected() {
|
sensor := lsm303agr.New(machine.I2C0)
|
||||||
println("LSM303AGR/MAG not connected!")
|
err := sensor.Configure(lsm303agr.Configuration{}) //default settings
|
||||||
return
|
if err != nil {
|
||||||
|
for {
|
||||||
|
println("Failed to configure", err.Error())
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accel_mag.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,
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
||||||
accel_x, accel_y, accel_z := accel_mag.ReadAcceleration()
|
if !sensor.Connected() {
|
||||||
pitch, roll := accel_mag.ReadPitchRoll()
|
println("LSM303AGR/MAG not connected!")
|
||||||
mag_x, mag_y, mag_z := accel_mag.ReadMagneticField()
|
time.Sleep(time.Second)
|
||||||
heading := accel_mag.ReadCompass()
|
continue
|
||||||
temp, _ := accel_mag.ReadTemperature()
|
}
|
||||||
|
|
||||||
|
// accel_x, accel_y, accel_z := sensor.ReadAcceleration()
|
||||||
|
// println("ACCEL_X:", accel_x/100000, " ACCEL_Y:", accel_y/100000, " ACCEL_Z:", accel_z/100000)
|
||||||
|
|
||||||
|
// 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")
|
println("\n")
|
||||||
|
time.Sleep(time.Millisecond * 250)
|
||||||
time.Sleep(time.Millisecond * 100)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,23 @@ func main() {
|
|||||||
machine.I2C0.Configure(machine.I2CConfig{})
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
accel := lsm6ds3.New(machine.I2C0)
|
accel := lsm6ds3.New(machine.I2C0)
|
||||||
accel.Configure(lsm6ds3.Configuration{})
|
err := accel.Configure(lsm6ds3.Configuration{})
|
||||||
if !accel.Connected() {
|
if err != nil {
|
||||||
println("LSM6DS3 not connected")
|
for {
|
||||||
return
|
println("Failed to configure", err.Error())
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
x, y, z := accel.ReadAcceleration()
|
if !accel.Connected() {
|
||||||
|
println("LSM6DS3 not connected")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
x, y, z, _ := accel.ReadAcceleration()
|
||||||
println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
|
println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
|
||||||
x, y, z = accel.ReadRotation()
|
x, y, z, _ = accel.ReadRotation()
|
||||||
println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
|
println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
|
||||||
x, _ = accel.ReadTemperature()
|
x, _ = accel.ReadTemperature()
|
||||||
println("Degrees C", float32(x)/1000, "\n\n")
|
println("Degrees C", float32(x)/1000, "\n\n")
|
||||||
|
|||||||
@@ -26,12 +26,18 @@ func main() {
|
|||||||
machine.I2C0.Configure(machine.I2CConfig{})
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
device := lsm6dsox.New(machine.I2C0)
|
device := lsm6dsox.New(machine.I2C0)
|
||||||
device.Configure(lsm6dsox.Configuration{
|
err := device.Configure(lsm6dsox.Configuration{
|
||||||
AccelRange: lsm6dsox.ACCEL_2G,
|
AccelRange: lsm6dsox.ACCEL_2G,
|
||||||
AccelSampleRate: lsm6dsox.ACCEL_SR_104,
|
AccelSampleRate: lsm6dsox.ACCEL_SR_104,
|
||||||
GyroRange: lsm6dsox.GYRO_250DPS,
|
GyroRange: lsm6dsox.GYRO_250DPS,
|
||||||
GyroSampleRate: lsm6dsox.GYRO_SR_104,
|
GyroSampleRate: lsm6dsox.GYRO_SR_104,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
for {
|
||||||
|
println("Failed to configure", err.Error())
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
||||||
@@ -46,8 +52,8 @@ func main() {
|
|||||||
calibrateGyro(device)
|
calibrateGyro(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
ax, ay, az := device.ReadAcceleration()
|
ax, ay, az, _ := device.ReadAcceleration()
|
||||||
gx, gy, gz := device.ReadRotation()
|
gx, gy, gz, _ := device.ReadRotation()
|
||||||
t, _ := device.ReadTemperature()
|
t, _ := device.ReadTemperature()
|
||||||
|
|
||||||
if PLOTTER {
|
if PLOTTER {
|
||||||
@@ -64,7 +70,7 @@ func main() {
|
|||||||
|
|
||||||
func calibrateGyro(device *lsm6dsox.Device) {
|
func calibrateGyro(device *lsm6dsox.Device) {
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
gx, gy, gz := device.ReadRotation()
|
gx, gy, gz, _ := device.ReadRotation()
|
||||||
cal[0] += float32(gx) / 1000000
|
cal[0] += float32(gx) / 1000000
|
||||||
cal[1] += float32(gy) / 1000000
|
cal[1] += float32(gy) / 1000000
|
||||||
cal[2] += float32(gz) / 1000000
|
cal[2] += float32(gz) / 1000000
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func main() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
||||||
if con, err := device.Connected(); !con || err != nil {
|
if !device.Connected() {
|
||||||
println("LSM9DS1 not connected")
|
println("LSM9DS1 not connected")
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ func main() {
|
|||||||
driver.StopDisplayTest()
|
driver.StopDisplayTest()
|
||||||
driver.SetDecodeMode(4)
|
driver.SetDecodeMode(4)
|
||||||
driver.SetScanLimit(4)
|
driver.SetScanLimit(4)
|
||||||
|
driver.SetIntensity(8)
|
||||||
driver.StopShutdownMode()
|
driver.StopShutdownMode()
|
||||||
|
|
||||||
for i := 1; i < int(digitNumber); i++ {
|
for i := 1; i < int(digitNumber); i++ {
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -65,7 +65,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func run() error {
|
|||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
http.SetBuf(buf[:])
|
http.SetBuf(buf[:])
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func run() error {
|
|||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
http.SetBuf(buf[:])
|
http.SetBuf(buf[:])
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func run() error {
|
|||||||
http.SetBuf(buf[:])
|
http.SetBuf(buf[:])
|
||||||
|
|
||||||
fmt.Fprintf(terminal, "ConnectToAP()\r\n")
|
fmt.Fprintf(terminal, "ConnectToAP()\r\n")
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func run() error {
|
|||||||
net.UseDriver(rtl)
|
net.UseDriver(rtl)
|
||||||
http.SetBuf(buf[:])
|
http.SetBuf(buf[:])
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
http.UseDriver(rtl)
|
http.UseDriver(rtl)
|
||||||
|
|
||||||
err = rtl.ConnectToAP(ssid, password)
|
err = rtl.ConnectToAccessPoint(ssid, password, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,68 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
"machine"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/ssd1289"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
//The SSD1289 is configured in 16 bit parallel mode and requires 16 GPIOs
|
||||||
|
//The Pin bus is the most flexible but ineffecient method it switches
|
||||||
|
//individual pins on and off. If you are able to use consecutive pins
|
||||||
|
//consider creating a more efficient bus implementation that uses
|
||||||
|
//your microcontrollers built in "ports"
|
||||||
|
//see rp2040bus.go for an example for the rapsberry pi pico
|
||||||
|
bus := ssd1289.NewPinBus([16]machine.Pin{
|
||||||
|
machine.GP4, //DB0
|
||||||
|
machine.GP5, //DB1
|
||||||
|
machine.GP6, //DB2
|
||||||
|
machine.GP7, //DB3
|
||||||
|
machine.GP8, //DB4
|
||||||
|
machine.GP9, //DB5
|
||||||
|
machine.GP10, //DB6
|
||||||
|
machine.GP11, //DB7
|
||||||
|
machine.GP12, //DB8
|
||||||
|
machine.GP13, //DB9
|
||||||
|
machine.GP14, //DB10
|
||||||
|
machine.GP15, //DB11
|
||||||
|
machine.GP16, //DB12
|
||||||
|
machine.GP17, //DB13
|
||||||
|
machine.GP18, //DB14
|
||||||
|
machine.GP19, //DB15
|
||||||
|
})
|
||||||
|
|
||||||
|
//Control pins for the SSD1289
|
||||||
|
rs := machine.GP0
|
||||||
|
wr := machine.GP1
|
||||||
|
cs := machine.GP2
|
||||||
|
rst := machine.GP3
|
||||||
|
|
||||||
|
display := ssd1289.New(rs, wr, cs, rst, bus)
|
||||||
|
|
||||||
|
display.Configure() //Sends intialization sequence to SSD1289.
|
||||||
|
//!! After configure the display will contain random data and needs to be cleared
|
||||||
|
|
||||||
|
background := color.RGBA{0, 0, 0, 255} //Black
|
||||||
|
display.FillDisplay(background) //Clears the display to the given color
|
||||||
|
|
||||||
|
for {
|
||||||
|
//Draw random filled coloured rectangles
|
||||||
|
x := int16(rand.Intn(120))
|
||||||
|
w := int16(rand.Intn(120))
|
||||||
|
|
||||||
|
y := int16(rand.Intn(160))
|
||||||
|
h := int16(rand.Intn(160))
|
||||||
|
|
||||||
|
r := uint8(rand.Intn(255))
|
||||||
|
g := uint8(rand.Intn(255))
|
||||||
|
b := uint8(rand.Intn(255))
|
||||||
|
|
||||||
|
c := color.RGBA{r, g, b, 255}
|
||||||
|
|
||||||
|
display.FillRect(x, y, w, h, c) //Fills the given rectangle the rest of the display is unaffected.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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++
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -128,19 +128,15 @@ func waitSerial() {
|
|||||||
|
|
||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
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)
|
time.Sleep(2 * time.Second)
|
||||||
println("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
println("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,22 +132,18 @@ func waitSerial() {
|
|||||||
|
|
||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
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 {
|
for {
|
||||||
println("Connection failed: Either ssid or password not set")
|
println(err)
|
||||||
time.Sleep(10 * 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)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
message("Connected.")
|
}
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
|
println("Connected.")
|
||||||
|
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
message(err.Error())
|
message(err.Error())
|
||||||
|
|||||||
@@ -104,14 +104,16 @@ func main() {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
println("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
println("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
println(err.Error())
|
println(err.Error())
|
||||||
|
|||||||
@@ -116,13 +116,16 @@ func publishing() {
|
|||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
println("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
println("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
println("Connected.")
|
println("Connected.")
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
|
|||||||
@@ -151,21 +151,18 @@ func clearBuffer() {
|
|||||||
|
|
||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
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)
|
time.Sleep(2 * time.Second)
|
||||||
message("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
message("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
message("Connected.")
|
}
|
||||||
|
|
||||||
|
println("Connected.")
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
|
|||||||
@@ -113,14 +113,17 @@ func sendBatch() {
|
|||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
message("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
message("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
message("Connected.")
|
}
|
||||||
|
|
||||||
|
println("Connected.")
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
|
|||||||
@@ -122,21 +122,18 @@ func makeHTTPSRequest() {
|
|||||||
|
|
||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
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)
|
time.Sleep(2 * time.Second)
|
||||||
message("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
message("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
message("Connected.")
|
}
|
||||||
|
|
||||||
|
println("Connected.")
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
|
|||||||
@@ -76,15 +76,17 @@ func main() {
|
|||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
func connectToAP() {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
message("Connecting to " + ssid)
|
println("Connecting to " + ssid)
|
||||||
adaptor.SetPassphrase(ssid, pass)
|
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
|
||||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
if err != nil { // error connecting to AP
|
||||||
message("Connection status: " + st.String())
|
for {
|
||||||
|
println(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
message("Connected.")
|
}
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
|
println("Connected.")
|
||||||
|
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
message(err.Error())
|
message(err.Error())
|
||||||
|
|||||||
@@ -124,22 +124,18 @@ func makeHTTPRequest() {
|
|||||||
|
|
||||||
// connect to access point
|
// connect to access point
|
||||||
func connectToAP() {
|
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 {
|
for {
|
||||||
println("Connection failed: Either ssid or password not set")
|
println(err)
|
||||||
time.Sleep(10 * 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)
|
time.Sleep(1 * time.Second)
|
||||||
st, _ = adaptor.GetConnectionStatus()
|
|
||||||
}
|
}
|
||||||
message("Connected.")
|
}
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
|
println("Connected.")
|
||||||
|
|
||||||
ip, _, _, err := adaptor.GetIP()
|
ip, _, _, err := adaptor.GetIP()
|
||||||
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
|
||||||
message(err.Error())
|
message(err.Error())
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build !digispark && !arduino && !qtpy
|
//go:build !digispark && !arduino && !qtpy && !m5stamp_c3
|
||||||
// +build !digispark,!arduino,!qtpy
|
// +build !digispark,!arduino,!qtpy,!m5stamp_c3
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build qtpy || m5stamp_c3
|
||||||
|
// +build qtpy m5stamp_c3
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
// Replace neo and led in the code below to match the pin
|
||||||
|
// that you are using if different.
|
||||||
|
var neo machine.Pin = machine.WS2812
|
||||||
|
var led = machine.NoPin
|
||||||
@@ -5,11 +5,6 @@ package main
|
|||||||
|
|
||||||
import "machine"
|
import "machine"
|
||||||
|
|
||||||
// Replace neo and led in the code below to match the pin
|
|
||||||
// that you are using if different.
|
|
||||||
var neo machine.Pin = machine.NEOPIXELS
|
|
||||||
var led = machine.NoPin
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
pwr := machine.NEOPIXELS_POWER
|
pwr := machine.NEOPIXELS_POWER
|
||||||
pwr.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
pwr.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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]
|
||||||
|
}
|
||||||
@@ -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
@@ -105,7 +105,8 @@ func (g *GPIO) Read(data []byte) (n int, err error) {
|
|||||||
data[i] = g.read()
|
data[i] = g.read()
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
g.reconfigureGPIOMode(machine.PinInput)
|
g.rw.Low()
|
||||||
|
g.reconfigureGPIOMode(machine.PinOutput)
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +114,7 @@ func (g *GPIO) read4BitMode() byte {
|
|||||||
g.en.High()
|
g.en.High()
|
||||||
data := (g.pins() << 4 & 0xF0)
|
data := (g.pins() << 4 & 0xF0)
|
||||||
g.en.Low()
|
g.en.Low()
|
||||||
|
|
||||||
g.en.High()
|
g.en.High()
|
||||||
data |= (g.pins() & 0x0F)
|
data |= (g.pins() & 0x0F)
|
||||||
g.en.Low()
|
g.en.Low()
|
||||||
|
|||||||
+1
-1
@@ -126,7 +126,7 @@ func (d *Device) Configure(cfg Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if d.datalength == DATA_LENGTH_4BIT {
|
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
|
// Busy flag is now accessible
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const (
|
|||||||
|
|
||||||
FUNCTION_MODE = 0x20
|
FUNCTION_MODE = 0x20
|
||||||
DATA_LENGTH_8BIT = FUNCTION_MODE | 0x10
|
DATA_LENGTH_8BIT = FUNCTION_MODE | 0x10
|
||||||
DATA_LENGTH_4BIT = FUNCTION_MODE | 0x0
|
DATA_LENGTH_4BIT = FUNCTION_MODE | 0x2
|
||||||
TWO_LINE = FUNCTION_MODE | 0x8
|
TWO_LINE = FUNCTION_MODE | 0x8
|
||||||
ONE_LINE = FUNCTION_MODE | 0x0
|
ONE_LINE = FUNCTION_MODE | 0x0
|
||||||
FONT_5X10 = FUNCTION_MODE | 0x4
|
FONT_5X10 = FUNCTION_MODE | 0x4
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func (d *Device) Configure(cfg Config) error {
|
|||||||
return nil
|
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() {
|
func (d *Device) ClearDisplay() {
|
||||||
d.sendCommand(DISPLAY_CLEAR)
|
d.sendCommand(DISPLAY_CLEAR)
|
||||||
d.cursor.x = 0
|
d.cursor.x = 0
|
||||||
@@ -119,7 +119,8 @@ func (d *Device) Home() {
|
|||||||
|
|
||||||
// SetCursor sets the cursor to a specific position (x, y).
|
// 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) {
|
func (d *Device) SetCursor(x, y uint8) {
|
||||||
rowOffset := []uint8{0x0, 0x40, 0x14, 0x54}
|
rowOffset := []uint8{0x0, 0x40, 0x14, 0x54}
|
||||||
if y > (d.height - 1) {
|
if y > (d.height - 1) {
|
||||||
@@ -139,11 +140,11 @@ func (d *Device) Print(data []byte) {
|
|||||||
if chr == '\n' {
|
if chr == '\n' {
|
||||||
d.newLine()
|
d.newLine()
|
||||||
} else {
|
} else {
|
||||||
d.cursor.x++
|
|
||||||
if d.cursor.x >= d.width {
|
if d.cursor.x >= d.width {
|
||||||
d.newLine()
|
d.newLine()
|
||||||
}
|
}
|
||||||
d.sendData(uint8(rune(chr)))
|
d.sendData(uint8(rune(chr)))
|
||||||
|
d.cursor.x++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -21,6 +21,14 @@ type Device struct {
|
|||||||
temperatureZero 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.
|
// Connected returns whether HTS221 has been found.
|
||||||
// It does a "who am I" request and checks the response.
|
// It does a "who am I" request and checks the response.
|
||||||
func (d *Device) Connected() bool {
|
func (d *Device) Connected() bool {
|
||||||
@@ -29,14 +37,6 @@ func (d *Device) Connected() bool {
|
|||||||
return data[0] == 0xBC
|
return data[0] == 0xBC
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Power is for turn on/off the HTS221 device
|
// Power is for turn on/off the HTS221 device
|
||||||
func (d *Device) Power(status bool) {
|
func (d *Device) Power(status bool) {
|
||||||
data := []byte{0}
|
data := []byte{0}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ package hts221
|
|||||||
|
|
||||||
import "tinygo.org/x/drivers"
|
import "tinygo.org/x/drivers"
|
||||||
|
|
||||||
// New creates a new HTS221 connection. The I2C bus must already be
|
// Configure sets up the HTS221 device for communication.
|
||||||
// configured.
|
func (d *Device) Configure() {
|
||||||
//
|
// read calibration data
|
||||||
// This function only creates the Device object, it does not touch the device.
|
d.calibration()
|
||||||
func New(bus drivers.I2C) Device {
|
// activate device and use block data update mode
|
||||||
return Device{bus: bus, Address: HTS221_ADDRESS}
|
d.Power(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,24 +6,20 @@ package hts221
|
|||||||
import (
|
import (
|
||||||
"machine"
|
"machine"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/drivers"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// New creates a new HTS221 connection. The I2C bus must already be
|
// Configure sets up the HTS221 device for communication.
|
||||||
// configured.
|
func (d *Device) Configure() {
|
||||||
//
|
// Following lines are Nano 33 BLE specific, they have nothing to do with sensor per se
|
||||||
// This function only creates the Device object, it does not touch the device.
|
machine.HTS_PWR.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
func New(bus drivers.I2C) Device {
|
machine.HTS_PWR.High()
|
||||||
// turn on internal power pin (machine.P0_22) and I2C1 pullups power pin (machine.P1_00)
|
machine.I2C_PULLUP.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
// and wait a moment.
|
machine.I2C_PULLUP.High()
|
||||||
ENV := machine.P0_22
|
// Wait a moment
|
||||||
ENV.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
time.Sleep(10 * time.Millisecond)
|
||||||
ENV.High()
|
|
||||||
R := machine.P1_00
|
|
||||||
R.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
||||||
R.High()
|
|
||||||
time.Sleep(time.Millisecond * 10)
|
|
||||||
|
|
||||||
return Device{bus: bus, Address: HTS221_ADDRESS}
|
// read calibration data
|
||||||
|
d.calibration()
|
||||||
|
// activate device and use block data update mode
|
||||||
|
d.Power(true)
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-43
@@ -11,6 +11,7 @@ type Config struct {
|
|||||||
Width int16
|
Width int16
|
||||||
Height int16
|
Height int16
|
||||||
Rotation Rotation
|
Rotation Rotation
|
||||||
|
DisplayInversion bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
@@ -28,6 +29,33 @@ type Device struct {
|
|||||||
rd machine.Pin
|
rd machine.Pin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cmdBuf [6]byte
|
||||||
|
|
||||||
|
var initCmd = []byte{
|
||||||
|
0xEF, 3, 0x03, 0x80, 0x02,
|
||||||
|
0xCF, 3, 0x00, 0xC1, 0x30,
|
||||||
|
0xED, 4, 0x64, 0x03, 0x12, 0x81,
|
||||||
|
0xE8, 3, 0x85, 0x00, 0x78,
|
||||||
|
0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02,
|
||||||
|
0xF7, 1, 0x20,
|
||||||
|
0xEA, 2, 0x00, 0x00,
|
||||||
|
PWCTR1, 1, 0x23, // Power control VRH[5:0]
|
||||||
|
PWCTR2, 1, 0x10, // Power control SAP[2:0];BT[3:0]
|
||||||
|
VMCTR1, 2, 0x3e, 0x28, // VCM control
|
||||||
|
VMCTR2, 1, 0x86, // VCM control2
|
||||||
|
MADCTL, 1, 0x48, // Memory Access Control
|
||||||
|
VSCRSADD, 1, 0x00, // Vertical scroll zero
|
||||||
|
PIXFMT, 1, 0x55,
|
||||||
|
FRMCTR1, 2, 0x00, 0x18,
|
||||||
|
DFUNCTR, 3, 0x08, 0x82, 0x27, // Display Function Control
|
||||||
|
0xF2, 1, 0x00, // 3Gamma Function Disable
|
||||||
|
GAMMASET, 1, 0x01, // Gamma curve selected
|
||||||
|
GMCTRP1, 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma
|
||||||
|
0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
|
||||||
|
GMCTRN1, 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma
|
||||||
|
0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
|
||||||
|
}
|
||||||
|
|
||||||
// Configure prepares display for use
|
// Configure prepares display for use
|
||||||
func (d *Device) Configure(config Config) {
|
func (d *Device) Configure(config Config) {
|
||||||
|
|
||||||
@@ -80,33 +108,15 @@ func (d *Device) Configure(config Config) {
|
|||||||
delay(150)
|
delay(150)
|
||||||
}
|
}
|
||||||
|
|
||||||
initCmd := []byte{
|
if config.DisplayInversion {
|
||||||
0xEF, 3, 0x03, 0x80, 0x02,
|
initCmd = append(initCmd, INVON, 0x80)
|
||||||
0xCF, 3, 0x00, 0xC1, 0x30,
|
}
|
||||||
0xED, 4, 0x64, 0x03, 0x12, 0x81,
|
|
||||||
0xE8, 3, 0x85, 0x00, 0x78,
|
initCmd = append(initCmd,
|
||||||
0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02,
|
|
||||||
0xF7, 1, 0x20,
|
|
||||||
0xEA, 2, 0x00, 0x00,
|
|
||||||
PWCTR1, 1, 0x23, // Power control VRH[5:0]
|
|
||||||
PWCTR2, 1, 0x10, // Power control SAP[2:0];BT[3:0]
|
|
||||||
VMCTR1, 2, 0x3e, 0x28, // VCM control
|
|
||||||
VMCTR2, 1, 0x86, // VCM control2
|
|
||||||
MADCTL, 1, 0x48, // Memory Access Control
|
|
||||||
VSCRSADD, 1, 0x00, // Vertical scroll zero
|
|
||||||
PIXFMT, 1, 0x55,
|
|
||||||
FRMCTR1, 2, 0x00, 0x18,
|
|
||||||
DFUNCTR, 3, 0x08, 0x82, 0x27, // Display Function Control
|
|
||||||
0xF2, 1, 0x00, // 3Gamma Function Disable
|
|
||||||
GAMMASET, 1, 0x01, // Gamma curve selected
|
|
||||||
GMCTRP1, 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma
|
|
||||||
0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
|
|
||||||
GMCTRN1, 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma
|
|
||||||
0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
|
|
||||||
SLPOUT, 0x80, // Exit Sleep
|
SLPOUT, 0x80, // Exit Sleep
|
||||||
DISPON, 0x80, // Display on
|
DISPON, 0x80, // Display on
|
||||||
0x00, // End of list
|
0x00, // End of list
|
||||||
}
|
)
|
||||||
for i, c := 0, len(initCmd); i < c; {
|
for i, c := 0, len(initCmd); i < c; {
|
||||||
cmd := initCmd[i]
|
cmd := initCmd[i]
|
||||||
if cmd == 0x00 {
|
if cmd == 0x00 {
|
||||||
@@ -239,34 +249,46 @@ func (d *Device) GetRotation() Rotation {
|
|||||||
// SetRotation changes the rotation of the device (clock-wise)
|
// SetRotation changes the rotation of the device (clock-wise)
|
||||||
func (d *Device) SetRotation(rotation Rotation) {
|
func (d *Device) SetRotation(rotation Rotation) {
|
||||||
madctl := uint8(0)
|
madctl := uint8(0)
|
||||||
switch rotation % 4 {
|
switch rotation % 8 {
|
||||||
case 0:
|
case Rotation0:
|
||||||
madctl = MADCTL_MX | MADCTL_BGR
|
madctl = MADCTL_MX | MADCTL_BGR
|
||||||
case 1:
|
case Rotation90:
|
||||||
madctl = MADCTL_MV | MADCTL_BGR
|
madctl = MADCTL_MV | MADCTL_BGR
|
||||||
case 2:
|
case Rotation180:
|
||||||
madctl = MADCTL_MY | MADCTL_BGR
|
madctl = MADCTL_MY | MADCTL_BGR
|
||||||
case 3:
|
case Rotation270:
|
||||||
|
madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR
|
||||||
|
case Rotation0Mirror:
|
||||||
|
madctl = MADCTL_BGR
|
||||||
|
case Rotation90Mirror:
|
||||||
|
madctl = MADCTL_MY | MADCTL_MV | MADCTL_BGR
|
||||||
|
case Rotation180Mirror:
|
||||||
|
madctl = MADCTL_MX | MADCTL_MY | MADCTL_BGR
|
||||||
|
case Rotation270Mirror:
|
||||||
madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR
|
madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR
|
||||||
}
|
}
|
||||||
d.sendCommand(MADCTL, []uint8{madctl})
|
cmdBuf[0] = madctl
|
||||||
|
d.sendCommand(MADCTL, cmdBuf[:1])
|
||||||
d.rotation = rotation
|
d.rotation = rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetScrollArea sets an area to scroll with fixed top/bottom or left/right parts of the display
|
// SetScrollArea sets an area to scroll with fixed top/bottom or left/right parts of the display
|
||||||
// Rotation affects scroll direction
|
// Rotation affects scroll direction
|
||||||
func (d *Device) SetScrollArea(topFixedArea, bottomFixedArea int16) {
|
func (d *Device) SetScrollArea(topFixedArea, bottomFixedArea int16) {
|
||||||
d.sendCommand(VSCRDEF, []uint8{
|
cmdBuf[0] = uint8(topFixedArea >> 8)
|
||||||
uint8(topFixedArea >> 8), uint8(topFixedArea),
|
cmdBuf[1] = uint8(topFixedArea)
|
||||||
uint8(d.height - topFixedArea - bottomFixedArea>>8),
|
cmdBuf[2] = uint8(d.height - topFixedArea - bottomFixedArea>>8)
|
||||||
uint8(d.height - topFixedArea - bottomFixedArea),
|
cmdBuf[3] = uint8(d.height - topFixedArea - bottomFixedArea)
|
||||||
uint8(bottomFixedArea >> 8), uint8(bottomFixedArea),
|
cmdBuf[4] = uint8(bottomFixedArea >> 8)
|
||||||
})
|
cmdBuf[5] = uint8(bottomFixedArea)
|
||||||
|
d.sendCommand(VSCRDEF, cmdBuf[:6])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetScroll sets the vertical scroll address of the display.
|
// SetScroll sets the vertical scroll address of the display.
|
||||||
func (d *Device) SetScroll(line int16) {
|
func (d *Device) SetScroll(line int16) {
|
||||||
d.sendCommand(VSCRSADD, []uint8{uint8(line >> 8), uint8(line)})
|
cmdBuf[0] = uint8(line >> 8)
|
||||||
|
cmdBuf[1] = uint8(line)
|
||||||
|
d.sendCommand(VSCRSADD, cmdBuf[:2])
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopScroll returns the display to its normal state
|
// StopScroll returns the display to its normal state
|
||||||
@@ -280,16 +302,20 @@ func (d *Device) setWindow(x, y, w, h int16) {
|
|||||||
//y += d.rowOffset
|
//y += d.rowOffset
|
||||||
x1 := x + w - 1
|
x1 := x + w - 1
|
||||||
if x != d.x0 || x1 != d.x1 {
|
if x != d.x0 || x1 != d.x1 {
|
||||||
d.sendCommand(CASET, []uint8{
|
cmdBuf[0] = uint8(x >> 8)
|
||||||
uint8(x >> 8), uint8(x), uint8(x1 >> 8), uint8(x1),
|
cmdBuf[1] = uint8(x)
|
||||||
})
|
cmdBuf[2] = uint8(x1 >> 8)
|
||||||
|
cmdBuf[3] = uint8(x1)
|
||||||
|
d.sendCommand(CASET, cmdBuf[:4])
|
||||||
d.x0, d.x1 = x, x1
|
d.x0, d.x1 = x, x1
|
||||||
}
|
}
|
||||||
y1 := y + h - 1
|
y1 := y + h - 1
|
||||||
if y != d.y0 || y1 != d.y1 {
|
if y != d.y0 || y1 != d.y1 {
|
||||||
d.sendCommand(PASET, []uint8{
|
cmdBuf[0] = uint8(y >> 8)
|
||||||
uint8(y >> 8), uint8(y), uint8(y1 >> 8), uint8(y1),
|
cmdBuf[1] = uint8(y)
|
||||||
})
|
cmdBuf[2] = uint8(y1 >> 8)
|
||||||
|
cmdBuf[3] = uint8(y1)
|
||||||
|
d.sendCommand(PASET, cmdBuf[:4])
|
||||||
d.y0, d.y1 = y, y1
|
d.y0, d.y1 = y, y1
|
||||||
}
|
}
|
||||||
d.sendCommand(RAMWR, nil)
|
d.sendCommand(RAMWR, nil)
|
||||||
|
|||||||
@@ -81,4 +81,9 @@ const (
|
|||||||
Rotation90 Rotation = 1 // 90 degrees clock-wise rotation
|
Rotation90 Rotation = 1 // 90 degrees clock-wise rotation
|
||||||
Rotation180 Rotation = 2
|
Rotation180 Rotation = 2
|
||||||
Rotation270 Rotation = 3
|
Rotation270 Rotation = 3
|
||||||
|
|
||||||
|
Rotation0Mirror Rotation = 4
|
||||||
|
Rotation90Mirror Rotation = 5
|
||||||
|
Rotation180Mirror Rotation = 6
|
||||||
|
Rotation270Mirror Rotation = 7
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
//go:build !atsamd51 && !atsamd21
|
//go:build !atsamd51 && !atsame5x && !atsamd21
|
||||||
// +build !atsamd51,!atsamd21
|
// +build !atsamd51,!atsame5x,!atsamd21
|
||||||
|
|
||||||
package ili9341
|
package ili9341
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build atsamd51
|
//go:build atsamd51 || atsame5x
|
||||||
// +build atsamd51
|
// +build atsamd51 atsame5x
|
||||||
|
|
||||||
package ili9341
|
package ili9341
|
||||||
|
|
||||||
|
|||||||
@@ -773,10 +773,10 @@ func (d *decoder) convertToRGB() (image.Image, error) {
|
|||||||
|
|
||||||
// Decode reads a JPEG image from r. Different from the standard package, the
|
// Decode reads a JPEG image from r. Different from the standard package, the
|
||||||
// decoded result will be received by the callback set by SetCallback().
|
// decoded result will be received by the callback set by SetCallback().
|
||||||
func Decode(r io.Reader) error {
|
func Decode(r io.Reader) (image.Image, error) {
|
||||||
var d decoder
|
var d decoder
|
||||||
_, err := d.decode(r, false)
|
_, err := d.decode(r, false)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeConfig returns the color model and dimensions of a JPEG image without
|
// DecodeConfig returns the color model and dimensions of a JPEG image without
|
||||||
|
|||||||
+4
-4
@@ -965,7 +965,7 @@ func (d *decoder) checkHeader() error {
|
|||||||
|
|
||||||
// Decode reads a PNG image from r. Different from the standard package, the
|
// Decode reads a PNG image from r. Different from the standard package, the
|
||||||
// decoded result will be received by the callback set by SetCallback().
|
// decoded result will be received by the callback set by SetCallback().
|
||||||
func Decode(r io.Reader) error {
|
func Decode(r io.Reader) (image.Image, error) {
|
||||||
d := &decoder{
|
d := &decoder{
|
||||||
r: r,
|
r: r,
|
||||||
crc: crc32.NewIEEE(),
|
crc: crc32.NewIEEE(),
|
||||||
@@ -974,17 +974,17 @@ func Decode(r io.Reader) error {
|
|||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
for d.stage != dsSeenIEND {
|
for d.stage != dsSeenIEND {
|
||||||
if err := d.parseChunk(); err != nil {
|
if err := d.parseChunk(); err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeConfig returns the color model and dimensions of a PNG image without
|
// DecodeConfig returns the color model and dimensions of a PNG image without
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
package irremote // import "tinygo.org/x/drivers/irremote"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NEC protocol references
|
||||||
|
// https://www.sbprojects.net/knowledge/ir/nec.php
|
||||||
|
// https://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol
|
||||||
|
// https://simple-circuit.com/arduino-nec-remote-control-decoder/
|
||||||
|
|
||||||
|
// Data encapsulates the data received by the ReceiverDevice.
|
||||||
|
type Data struct {
|
||||||
|
// Code is the raw IR data received.
|
||||||
|
Code uint32
|
||||||
|
// Address is the decoded address from the IR data received.
|
||||||
|
Address uint16
|
||||||
|
// Command is the decoded command from the IR data recieved
|
||||||
|
Command uint16
|
||||||
|
// Flags provides additional information about the IR data received. See DataFlags
|
||||||
|
Flags DataFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataFlags provides bitwise flags representing various information about recieved IR data.
|
||||||
|
type DataFlags uint16
|
||||||
|
|
||||||
|
// Valid values for DataFlags
|
||||||
|
const (
|
||||||
|
// DataFlagIsRepeat set indicates that the IR data is a repeat commmand
|
||||||
|
DataFlagIsRepeat DataFlags = 1 << iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommandHandler defines the callback function used to provide IR data received by the ReceiverDevice.
|
||||||
|
type CommandHandler func(data Data)
|
||||||
|
|
||||||
|
// nec_ir_state represents the various internal states used to decode the NEC IR protocol commands
|
||||||
|
type nec_ir_state uint8
|
||||||
|
|
||||||
|
// Valid values for nec_ir_state
|
||||||
|
const (
|
||||||
|
lead_pulse_start nec_ir_state = iota // Start receiving IR data, beginning of 9ms lead pulse
|
||||||
|
lead_space_start // End of 9ms lead pulse, start of 4.5ms space
|
||||||
|
lead_space_end // End of 4.5ms space, start of 562µs pulse
|
||||||
|
bit_read_start // End of 562µs pulse, start of 562µs or 1687µs space
|
||||||
|
bit_read_end // End of 562µs or 1687µs space
|
||||||
|
trail_pulse_end // End of 562µs trailing pulse
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReceiverDevice is the device for receiving IR commands
|
||||||
|
type ReceiverDevice struct {
|
||||||
|
pin machine.Pin // IR input pin.
|
||||||
|
ch CommandHandler // client callback function
|
||||||
|
necState nec_ir_state // internal state machine
|
||||||
|
data Data // decoded data for client
|
||||||
|
lastTime time.Time // used to track states
|
||||||
|
bitIndex int // tracks which bit (0-31) of necCode is being read
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReceiver returns a new IR receiver device
|
||||||
|
func NewReceiver(pin machine.Pin) ReceiverDevice {
|
||||||
|
return ReceiverDevice{pin: pin}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure configures the input pin for the IR receiver device
|
||||||
|
func (ir *ReceiverDevice) Configure() {
|
||||||
|
// The IR receiver sends logic HIGH when NOT receiving IR, and logic LOW when receiving IR
|
||||||
|
ir.pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCommandHandler is used to start or stop receiving IR commands via a callback function (pass nil to stop)
|
||||||
|
func (ir *ReceiverDevice) SetCommandHandler(ch CommandHandler) {
|
||||||
|
ir.ch = ch
|
||||||
|
ir.resetStateMachine()
|
||||||
|
if ch != nil {
|
||||||
|
// Start monitoring IR output pin for changes
|
||||||
|
ir.pin.SetInterrupt(machine.PinFalling|machine.PinRising, ir.pinChange)
|
||||||
|
} else {
|
||||||
|
// Stop monitoring IR output pin for changes
|
||||||
|
ir.pin.SetInterrupt(0, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal helper function to reset state machine on protocol failure
|
||||||
|
func (ir *ReceiverDevice) resetStateMachine() {
|
||||||
|
ir.data = Data{}
|
||||||
|
ir.bitIndex = 0
|
||||||
|
ir.necState = lead_pulse_start
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal pin rising/falling edge interrupt handler
|
||||||
|
func (ir *ReceiverDevice) pinChange(pin machine.Pin) {
|
||||||
|
/* Currently TinyGo is sending machine.NoPin (0xff) for all pins, at least on RP2040
|
||||||
|
if pin != ir.pin {
|
||||||
|
return // This is not the pin you're looking for
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
now := time.Now()
|
||||||
|
duration := now.Sub(ir.lastTime)
|
||||||
|
ir.lastTime = now
|
||||||
|
switch ir.necState {
|
||||||
|
case lead_pulse_start:
|
||||||
|
if !ir.pin.Get() {
|
||||||
|
// IR is 'on' (pin is pulled high and sent low when IR is received)
|
||||||
|
ir.necState = lead_space_start // move to next state
|
||||||
|
}
|
||||||
|
case lead_space_start:
|
||||||
|
if duration > time.Microsecond*9500 || duration < time.Microsecond*8500 {
|
||||||
|
// Invalid interval for 9ms lead pulse. Reset
|
||||||
|
ir.resetStateMachine()
|
||||||
|
} else {
|
||||||
|
// 9ms lead pulse detected, move to next state
|
||||||
|
ir.necState = lead_space_end
|
||||||
|
}
|
||||||
|
case lead_space_end:
|
||||||
|
if duration > time.Microsecond*5000 || duration < time.Microsecond*1750 {
|
||||||
|
// Invalid interval for 4.5ms lead space OR 2.25ms repeat space. Reset
|
||||||
|
ir.resetStateMachine()
|
||||||
|
} else {
|
||||||
|
// 4.5ms lead space OR 2.25ms repeat space detected
|
||||||
|
if duration > time.Microsecond*3000 {
|
||||||
|
// 4.5ms lead space detected, new code incoming, move to next state
|
||||||
|
ir.resetStateMachine()
|
||||||
|
ir.necState = bit_read_start
|
||||||
|
} else {
|
||||||
|
// 2.25ms repeat space detected.
|
||||||
|
if ir.data.Code != 0 {
|
||||||
|
// Valid repeat code. Invoke client callback with repeat flag set
|
||||||
|
ir.data.Flags |= DataFlagIsRepeat
|
||||||
|
if ir.ch != nil {
|
||||||
|
ir.ch(ir.data)
|
||||||
|
}
|
||||||
|
ir.necState = lead_pulse_start
|
||||||
|
} else {
|
||||||
|
// ir.data is not in a valid state for a repeat. Reset
|
||||||
|
ir.resetStateMachine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case bit_read_start:
|
||||||
|
if duration > time.Microsecond*700 || duration < time.Microsecond*400 {
|
||||||
|
// Invalid interval for 562.5µs pulse. Reset
|
||||||
|
ir.resetStateMachine()
|
||||||
|
} else {
|
||||||
|
// 562.5µs pulse detected, move to next state
|
||||||
|
ir.necState = bit_read_end
|
||||||
|
}
|
||||||
|
case bit_read_end:
|
||||||
|
if duration > time.Microsecond*1800 || duration < time.Microsecond*400 {
|
||||||
|
// Invalid interval for 562.5µs space OR 1687.5µs space. Reset
|
||||||
|
ir.resetStateMachine()
|
||||||
|
} else {
|
||||||
|
// 562.5µs OR 1687.5µs space detected
|
||||||
|
mask := uint32((1 << (31 - ir.bitIndex)))
|
||||||
|
if duration > time.Microsecond*1000 {
|
||||||
|
// 1687.5µs space detected (logic 1) - Set bit
|
||||||
|
ir.data.Code |= mask
|
||||||
|
} else {
|
||||||
|
// 562.5µs space detected (logic 0) - Clear bit
|
||||||
|
ir.data.Code &^= mask
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.bitIndex++
|
||||||
|
if ir.bitIndex > 31 {
|
||||||
|
// We've read all bits for this code, move to next state
|
||||||
|
ir.necState = trail_pulse_end
|
||||||
|
} else {
|
||||||
|
// Read next bit
|
||||||
|
ir.necState = bit_read_start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case trail_pulse_end:
|
||||||
|
if duration > time.Microsecond*700 || duration < time.Microsecond*400 {
|
||||||
|
// Invalid interval for trailing 562.5µs pulse. Reset
|
||||||
|
ir.resetStateMachine()
|
||||||
|
} else {
|
||||||
|
// 562.5µs trailing pulse detected. Decode & validate data
|
||||||
|
err := ir.decode()
|
||||||
|
if err == irDecodeErrorNone {
|
||||||
|
// Valid data, invoke client callback
|
||||||
|
if ir.ch != nil {
|
||||||
|
ir.ch(ir.data)
|
||||||
|
}
|
||||||
|
// around we go again. Note: we don't resetStateMachine() since repeat codes are now possible
|
||||||
|
ir.necState = lead_pulse_start
|
||||||
|
} else {
|
||||||
|
ir.resetStateMachine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error type for NEC format decoding
|
||||||
|
type irDecodeError int
|
||||||
|
|
||||||
|
// Valid values for irDecodeError
|
||||||
|
const (
|
||||||
|
irDecodeErrorNone irDecodeError = iota // no error occurred
|
||||||
|
irDecodeErrorInverseCheckFail // validation of inverse cmd does not match cmd
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ir *ReceiverDevice) decode() irDecodeError {
|
||||||
|
// Decode cmd and inverse cmd and perform validation check
|
||||||
|
cmd := uint8((ir.data.Code & 0xff00) >> 8)
|
||||||
|
invCmd := uint8(ir.data.Code & 0xff)
|
||||||
|
if cmd != ^invCmd {
|
||||||
|
// Validation failure. cmd and inverse cmd do not match
|
||||||
|
return irDecodeErrorInverseCheckFail
|
||||||
|
}
|
||||||
|
// cmd validation pass, decode address
|
||||||
|
ir.data.Command = uint16(cmd)
|
||||||
|
addrLow := uint8((ir.data.Code & 0xff000000) >> 24)
|
||||||
|
addrHigh := uint8((ir.data.Code & 0x00ff0000) >> 16)
|
||||||
|
if addrHigh == ^addrLow {
|
||||||
|
// addrHigh is inverse of addrLow. This is not a valid 16-bit address in extended NEC coding
|
||||||
|
// since it is indistinguishable from 8-bit address with inverse validation. Use the 8-bit address
|
||||||
|
ir.data.Address = uint16(addrLow)
|
||||||
|
} else {
|
||||||
|
// 16-bit extended NEC address
|
||||||
|
ir.data.Address = (uint16(addrHigh) << 8) | uint16(addrLow)
|
||||||
|
}
|
||||||
|
// Clear repeat flag
|
||||||
|
ir.data.Flags &^= DataFlagIsRepeat
|
||||||
|
return irDecodeErrorNone
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
// Package is31fl3731 provides a driver for the Lumissil IS31FL3731 matrix LED
|
||||||
|
// driver.
|
||||||
|
//
|
||||||
|
// Driver supports following layouts:
|
||||||
|
// - any custom LED matrix layout
|
||||||
|
// - Adafruit 15x7 CharliePlex LED Matrix FeatherWing (CharlieWing)
|
||||||
|
// https://www.adafruit.com/product/3163
|
||||||
|
//
|
||||||
|
// Datasheet:
|
||||||
|
// https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf
|
||||||
|
//
|
||||||
|
// This driver inspired by Adafruit Python driver:
|
||||||
|
// https://github.com/adafruit/Adafruit_CircuitPython_IS31FL3731
|
||||||
|
//
|
||||||
|
package is31fl3731
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device implements TinyGo driver for Lumissil IS31FL3731 matrix LED driver
|
||||||
|
type Device struct {
|
||||||
|
Address uint8
|
||||||
|
bus drivers.I2C
|
||||||
|
|
||||||
|
// Currently selected command register (one of the frame registers or the
|
||||||
|
// function register)
|
||||||
|
selectedCommand uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure chip for operating as a LED matrix display
|
||||||
|
func (d *Device) Configure() (err error) {
|
||||||
|
// Shutdown software
|
||||||
|
err = d.writeFunctionRegister(SET_SHUTDOWN, []byte{SOFTWARE_OFF})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to shutdown: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 10)
|
||||||
|
|
||||||
|
// Wake up software
|
||||||
|
err = d.writeFunctionRegister(SET_SHUTDOWN, []byte{SOFTWARE_ON})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to wake up: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set display to a picture mode ("auto frame play mode" and "audio frame play
|
||||||
|
// mode" are not supported in this version of the driver)
|
||||||
|
err = d.writeFunctionRegister(SET_DISPLAY_MODE, []byte{DISPLAY_MODE_PICTURE})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to switch to a picture move: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable LEDs that are present (soldered) on the board. From the datasheet:
|
||||||
|
// LEDs which are no connected must be off by LED Control Register (Frame
|
||||||
|
// Registers) or it will affect other LEDs
|
||||||
|
err = d.enableLEDs()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to enable LEDs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable audiosync
|
||||||
|
err = d.writeFunctionRegister(SET_AUDIOSYNC, []byte{AUDIOSYNC_OFF})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to disable audiosync: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all frames
|
||||||
|
for frame := FRAME_0; frame <= FRAME_7; frame++ {
|
||||||
|
err = d.Clear(frame)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to clear frame %d: %w", frame, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1st frame is displayed by default
|
||||||
|
err = d.SetActiveFrame(FRAME_0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set active frame: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// selectCommand selects command register, can be:
|
||||||
|
// - frame registers 0-7
|
||||||
|
// - function register
|
||||||
|
func (d *Device) selectCommand(command uint8) (err error) {
|
||||||
|
if command != d.selectedCommand {
|
||||||
|
d.selectedCommand = command
|
||||||
|
return d.bus.WriteRegister(d.Address, COMMAND, []byte{command})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeFunctionRegister selects the function register and writes data into it
|
||||||
|
func (d *Device) writeFunctionRegister(operation uint8, data []byte) (err error) {
|
||||||
|
err = d.selectCommand(FUNCTION)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.bus.WriteRegister(d.Address, operation, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// enableLEDs enables only LEDs that are soldered on the set board. Enabled
|
||||||
|
// all 16x9 LEDs by default
|
||||||
|
func (d *Device) enableLEDs() (err error) {
|
||||||
|
for frame := FRAME_0; frame <= FRAME_7; frame++ {
|
||||||
|
err = d.selectCommand(frame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable every LED (16 columns x 9 rows)
|
||||||
|
for i := uint8(0); i < 16; i++ {
|
||||||
|
err = d.bus.WriteRegister(d.Address, i, []byte{0xFF})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setPixelPWD sets individual pixel's PWM value [0-255] on the selected frame
|
||||||
|
func (d *Device) setPixelPWD(frame, n, value uint8) (err error) {
|
||||||
|
err = d.selectCommand(frame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.bus.WriteRegister(d.Address, LED_PWM_OFFSET+n, []byte{value})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetActiveFrame sets frame to display with LEDs
|
||||||
|
func (d *Device) SetActiveFrame(frame uint8) (err error) {
|
||||||
|
if frame > FRAME_7 {
|
||||||
|
return fmt.Errorf("frame %d is out of valid range [0-7]", frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.writeFunctionRegister(SET_ACTIVE_FRAME, []byte{frame})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the whole frame with provided PWM value [0-255]
|
||||||
|
func (d *Device) Fill(frame, value uint8) (err error) {
|
||||||
|
if frame > FRAME_7 {
|
||||||
|
return fmt.Errorf("frame %d is out of valid range [0-7]", frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.selectCommand(frame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]byte, 24)
|
||||||
|
for i := range data {
|
||||||
|
data[i] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := uint8(0); i < 6; i++ {
|
||||||
|
err = d.bus.WriteRegister(d.Address, LED_PWM_OFFSET+i*24, data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the whole frame
|
||||||
|
func (d *Device) Clear(frame uint8) (err error) {
|
||||||
|
return d.Fill(frame, 0x00)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawPixelIndex draws a single pixel on the selected frame by its index with
|
||||||
|
// provided PWM value [0-255]
|
||||||
|
func (d *Device) DrawPixelIndex(frame, index, value uint8) (err error) {
|
||||||
|
if frame > FRAME_7 {
|
||||||
|
return fmt.Errorf("frame %d is out of valid range [0-7]", frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.setPixelPWD(frame, index, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawPixelXY draws a single pixel on the selected frame by its XY coordinates
|
||||||
|
// with provided PWM value [0-255]. Raw LEDs layout assumed to be a 16x9 matrix,
|
||||||
|
// and can be used with any custom board that has IS31FL3731 driver.
|
||||||
|
func (d *Device) DrawPixelXY(frame, x, y, value uint8) (err error) {
|
||||||
|
return d.setPixelPWD(frame, 16*x+y, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a raw driver w/o any preset board layout.
|
||||||
|
// Addresses:
|
||||||
|
// - 0x74 (AD pin connected to GND)
|
||||||
|
// - 0x75 (AD pin connected to SCL)
|
||||||
|
// - 0x76 (AD pin connected to SDA)
|
||||||
|
// - 0x77 (AD pin connected to VCC)
|
||||||
|
func New(bus drivers.I2C, address uint8) Device {
|
||||||
|
return Device{
|
||||||
|
Address: address,
|
||||||
|
bus: bus,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package is31fl3731
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeviceAdafruitCharlieWing15x7 implements TinyGo driver for Lumissil
|
||||||
|
// IS31FL3731 matrix LED driver on Adafruit 15x7 CharliePlex LED Matrix
|
||||||
|
// FeatherWing (CharlieWing) board: https://www.adafruit.com/product/3163
|
||||||
|
type DeviceAdafruitCharlieWing15x7 struct {
|
||||||
|
Device
|
||||||
|
}
|
||||||
|
|
||||||
|
// enableLEDs enables only LEDs that are soldered on the Adafruit CharlieWing
|
||||||
|
// board. The board has following LEDs matrix layout:
|
||||||
|
//
|
||||||
|
// "o" - connected (soldered) LEDs
|
||||||
|
// "x" - not connected LEDs
|
||||||
|
//
|
||||||
|
// + - - - - - - - - - - - - - - +
|
||||||
|
// | + - - - - - - - - - - - - + |
|
||||||
|
// | | | |
|
||||||
|
// | | v v
|
||||||
|
// +---------------------------------+
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | o o o o o o o o o o o o o o o x |
|
||||||
|
// | x x x x x x x x x x x x x x x x |
|
||||||
|
// +---------------------------------+
|
||||||
|
// ^ ^ | |
|
||||||
|
// | | ... - - + |
|
||||||
|
// | + - - - - - - - - - - - - - +
|
||||||
|
// |
|
||||||
|
// start (address 0x00)
|
||||||
|
//
|
||||||
|
func (d *DeviceAdafruitCharlieWing15x7) enableLEDs() (err error) {
|
||||||
|
for frame := FRAME_0; frame <= FRAME_7; frame++ {
|
||||||
|
err = d.selectCommand(frame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable left half
|
||||||
|
for i := uint8(0); i < 16; i += 2 {
|
||||||
|
err = d.bus.WriteRegister(d.Address, i, []byte{0b11111110})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Enable right half
|
||||||
|
for i := uint8(3); i < 16; i += 2 {
|
||||||
|
err = d.bus.WriteRegister(d.Address, i, []byte{0b01111111})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Disable invisible column on the right side
|
||||||
|
err = d.bus.WriteRegister(d.Address, 1, []byte{0b00000000})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawPixelXY draws a single pixel on the selected frame by its XY coordinates
|
||||||
|
// with provided PWM value [0-255]
|
||||||
|
func (d *DeviceAdafruitCharlieWing15x7) DrawPixelXY(frame, x, y, value uint8) (err error) {
|
||||||
|
var index uint8
|
||||||
|
|
||||||
|
if x >= 15 {
|
||||||
|
return fmt.Errorf("invalid value: X is out of range [0, 15]")
|
||||||
|
} else if y >= 7 {
|
||||||
|
return fmt.Errorf("invalid value: Y is out of range [0, 7]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Board is one pixel shorter (7 vs 8 supported pixels)
|
||||||
|
if x < 8 {
|
||||||
|
index = 16*x + y + 1
|
||||||
|
} else {
|
||||||
|
index = 16*(16-x) - y - 1 - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.setPixelPWD(frame, index, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAdafruitCharlieWing15x7 creates a new driver with Adafruit 15x7
|
||||||
|
// CharliePlex LED Matrix FeatherWing (CharlieWing) layout.
|
||||||
|
// Available addresses:
|
||||||
|
// - 0x74 (default)
|
||||||
|
// - 0x77 (when the address jumper soldered)
|
||||||
|
func NewAdafruitCharlieWing15x7(bus drivers.I2C, address uint8) DeviceAdafruitCharlieWing15x7 {
|
||||||
|
return DeviceAdafruitCharlieWing15x7{
|
||||||
|
Device: Device{
|
||||||
|
Address: address,
|
||||||
|
bus: bus,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package is31fl3731
|
||||||
|
|
||||||
|
// Registers. Names taken from the datasheet:
|
||||||
|
// https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf
|
||||||
|
const (
|
||||||
|
// AD pin connected to GND
|
||||||
|
I2C_ADDRESS_74 uint8 = 0x74
|
||||||
|
// AD pin connected to SCL
|
||||||
|
I2C_ADDRESS_75 uint8 = 0x75
|
||||||
|
// AD pin connected to SDA
|
||||||
|
I2C_ADDRESS_76 uint8 = 0x76
|
||||||
|
// AD pin connected to VCC
|
||||||
|
I2C_ADDRESS_77 uint8 = 0x77
|
||||||
|
|
||||||
|
// Main command register
|
||||||
|
COMMAND uint8 = 0xFD
|
||||||
|
|
||||||
|
// Commands for each of 8 frames
|
||||||
|
FRAME_0 uint8 = 0x00
|
||||||
|
FRAME_1 uint8 = 0x01
|
||||||
|
FRAME_2 uint8 = 0x02
|
||||||
|
FRAME_3 uint8 = 0x03
|
||||||
|
FRAME_4 uint8 = 0x04
|
||||||
|
FRAME_5 uint8 = 0x05
|
||||||
|
FRAME_6 uint8 = 0x06
|
||||||
|
FRAME_7 uint8 = 0x07
|
||||||
|
|
||||||
|
// Command to set configuration
|
||||||
|
FUNCTION uint8 = 0x0B
|
||||||
|
|
||||||
|
// Configuration:
|
||||||
|
SET_DISPLAY_MODE uint8 = 0x00
|
||||||
|
SET_ACTIVE_FRAME uint8 = 0x01
|
||||||
|
SET_AUDIOSYNC uint8 = 0x06
|
||||||
|
SET_SHUTDOWN uint8 = 0x0A
|
||||||
|
|
||||||
|
// Configuration: display mode
|
||||||
|
DISPLAY_MODE_PICTURE uint8 = 0x00
|
||||||
|
|
||||||
|
// Configuration: audiosync (enable audio signal to modulate the intensity of
|
||||||
|
// the matrix)
|
||||||
|
AUDIOSYNC_OFF uint8 = 0x00
|
||||||
|
AUDIOSYNC_ON uint8 = 0x01
|
||||||
|
|
||||||
|
// Configuration: software shutdown
|
||||||
|
SOFTWARE_OFF uint8 = 0x00
|
||||||
|
SOFTWARE_ON uint8 = 0x01
|
||||||
|
|
||||||
|
// Frame LEDs
|
||||||
|
LED_CONTROL_OFFSET uint8 = 0x00 // to on/off each LED
|
||||||
|
LED_PWM_OFFSET uint8 = 0x24 // to set PWM (0-255) for each LED
|
||||||
|
)
|
||||||
+141
@@ -0,0 +1,141 @@
|
|||||||
|
package l3gd20
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
fifoLen = 32 * 3 * 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type DevI2C struct {
|
||||||
|
addr uint8
|
||||||
|
// sensitivity or range.
|
||||||
|
mul int32
|
||||||
|
bus drivers.I2C
|
||||||
|
buf [1]byte
|
||||||
|
// gyro databuf.
|
||||||
|
databuf [6]byte
|
||||||
|
data [3]int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewI2C(bus drivers.I2C, addr uint8) *DevI2C {
|
||||||
|
return &DevI2C{
|
||||||
|
addr: addr,
|
||||||
|
bus: bus,
|
||||||
|
mul: sensMul250,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializes and configures the device.
|
||||||
|
func (d *DevI2C) Configure(cfg Config) error {
|
||||||
|
err := cfg.validate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = d.Reboot()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Reset then switch to normal mode and enable all three channels.
|
||||||
|
err = d.write8(CTRL_REG1, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = d.write8(CTRL_REG1, reg1NormalBits)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Reset REG2 values to default
|
||||||
|
err = d.write8(CTRL_REG3, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sensitivity
|
||||||
|
switch cfg.Range {
|
||||||
|
case 1: // debugging range
|
||||||
|
d.mul = 1
|
||||||
|
cfg.Range = Range_2000
|
||||||
|
case Range_250:
|
||||||
|
d.mul = sensMul250
|
||||||
|
case Range_500:
|
||||||
|
d.mul = sensMul500
|
||||||
|
case Range_2000:
|
||||||
|
d.mul = sensMul2000
|
||||||
|
default:
|
||||||
|
return ErrBadRange
|
||||||
|
}
|
||||||
|
err = d.write8(CTRL_REG4, cfg.Range)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Finally verify whomai register and return error if
|
||||||
|
// board is not who it says it is. Some counterfeit boards
|
||||||
|
// have incorrect whomai but can still be used.
|
||||||
|
whoami, err := d.read8(WHOAMI)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if whoami != expectedWHOAMI && whoami != expectedWHOAMI_H {
|
||||||
|
return ErrBadIdentity
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DevI2C) Update() error {
|
||||||
|
err := d.bus.ReadRegister(d.addr, OUT_X_L, d.databuf[:2])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = d.bus.ReadRegister(d.addr, OUT_Y_L, d.databuf[2:4])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = d.bus.ReadRegister(d.addr, OUT_Z_L, d.databuf[4:6])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
x := int16(binary.LittleEndian.Uint16(d.databuf[0:]))
|
||||||
|
y := int16(binary.LittleEndian.Uint16(d.databuf[2:]))
|
||||||
|
z := int16(binary.LittleEndian.Uint16(d.databuf[4:]))
|
||||||
|
d.data[0] = d.mul * int32(x)
|
||||||
|
d.data[1] = d.mul * int32(y)
|
||||||
|
d.data[2] = d.mul * int32(z)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reboot sets reboot bit in CTRL_REG5 to true and unsets it.
|
||||||
|
func (d *DevI2C) Reboot() error {
|
||||||
|
reg5, err := d.read8(CTRL_REG5)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Write reboot bit and then unset it.
|
||||||
|
err = d.write8(CTRL_REG5, reg5|reg5RebootBit)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(50 * time.Microsecond)
|
||||||
|
return d.write8(CTRL_REG5, reg5&^reg5RebootBit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AngularVelocity returns result in microradians per second.
|
||||||
|
func (d *DevI2C) AngularVelocity() (x, y, z int32) {
|
||||||
|
return d.data[0], d.data[1], d.data[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (d DevI2C) Update(measurement)
|
||||||
|
|
||||||
|
func (d DevI2C) read8(reg uint8) (byte, error) {
|
||||||
|
err := d.bus.ReadRegister(d.addr, reg, d.buf[:1])
|
||||||
|
return d.buf[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DevI2C) write8(reg uint8, val byte) error {
|
||||||
|
d.buf[0] = val
|
||||||
|
return d.bus.WriteRegister(d.addr, reg, d.buf[:1])
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package l3gd20
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrBadIdentity = errors.New("got unexpected identity from WHOMAI")
|
||||||
|
ErrBadRange = errors.New("bad range configuration value")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sensitivity factors
|
||||||
|
const (
|
||||||
|
// range at bits 4-5
|
||||||
|
// 00 = 250 dps
|
||||||
|
// 01 = 500 dps
|
||||||
|
// 10 = 2000 dps
|
||||||
|
// 11 = 2000 dps
|
||||||
|
rangePos = 4
|
||||||
|
Range_250 = 0b00 << rangePos // 8.75 mdps/digit
|
||||||
|
Range_500 = 0b01 << rangePos // 17.5 mdps/digit
|
||||||
|
Range_2000 = 0b11 << rangePos // 70 mdps/digit
|
||||||
|
rangebits = Range_250 | Range_500 | Range_2000
|
||||||
|
|
||||||
|
// Sensitivities for degrees
|
||||||
|
sensDiv250dps = 800
|
||||||
|
sensDiv500dps = 400
|
||||||
|
sensDiv2000dps = 100
|
||||||
|
sens_250 = 7. / sensDiv250dps // Sensitivity at 250 dps
|
||||||
|
sens_500 = 7. / sensDiv500dps // Sensitivity at 500 dps
|
||||||
|
sens_2000 = 7. / sensDiv2000dps // Sensitivity at 500 dp
|
||||||
|
|
||||||
|
// 1e6*Pi/180. = 17453.292519943298 (constant for Degree to micro radians conversion)
|
||||||
|
// sensitivities for radians
|
||||||
|
sensMul250 = 7 * 1745329 / 100 / sensDiv250dps
|
||||||
|
sensMul500 = 7 * 1745329 / 100 / sensDiv500dps
|
||||||
|
sensMul2000 = 7 * 1745329 / 100 / sensDiv2000dps
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Range uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate scans config for invalid data and returns non-nil
|
||||||
|
// error indicating what data must be modified.
|
||||||
|
func (cfg *Config) validate() error {
|
||||||
|
if cfg.Range&^rangebits != 0 && cfg.Range != 1 {
|
||||||
|
return ErrBadRange
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package l3gd20
|
||||||
|
|
||||||
|
// Expected identification number for L3GD20.
|
||||||
|
const (
|
||||||
|
// For L3GD20
|
||||||
|
expectedWHOAMI = 0xD4
|
||||||
|
// For L3GD20H
|
||||||
|
expectedWHOAMI_H = 0xD7
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register bits masks
|
||||||
|
const (
|
||||||
|
reg5RebootBit = 1 << 7
|
||||||
|
reg5FIFOEnableBit = 1 << 6
|
||||||
|
reg1NormalBits = 0b1111
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register addresses. Comments from https://github.com/adafruit/Adafruit_L3GD20_U/blob/master/Adafruit_L3GD20_U.cpp
|
||||||
|
const (
|
||||||
|
// The Slave ADdress (SAD) associated with the L3GD20 is 110101xb
|
||||||
|
I2CAddr = 0b1101011
|
||||||
|
// The SDO pin can be used to modify the less significant bit of the device address.
|
||||||
|
I2CAddrSDOLow = 0b1101010
|
||||||
|
WHOAMI uint8 = 0x0F
|
||||||
|
// CTRL_REG1 (0x20)
|
||||||
|
// ====================================================================
|
||||||
|
// BIT Symbol Description Default
|
||||||
|
// --- ------ --------------------------------------------- -------
|
||||||
|
// 7-6 DR1/0 Output data rate 00
|
||||||
|
// 5-4 BW1/0 Bandwidth selection 00
|
||||||
|
// 3 PD 0 = Power-down mode, 1 = normal/sleep mode 0
|
||||||
|
// 2 ZEN Z-axis enable (0 = disabled, 1 = enabled) 1
|
||||||
|
// 1 YEN Y-axis enable (0 = disabled, 1 = enabled) 1
|
||||||
|
// 0 XEN X-axis enable (0 = disabled, 1 = enabled) 1
|
||||||
|
CTRL_REG1 uint8 = 0x20
|
||||||
|
// Set CTRL_REG2 (0x21)
|
||||||
|
// ====================================================================
|
||||||
|
// BIT Symbol Description Default
|
||||||
|
// --- ------ --------------------------------------------- -------
|
||||||
|
// 5-4 HPM1/0 High-pass filter mode selection 00
|
||||||
|
// 3-0 HPCF3..0 High-pass filter cutoff frequency selection 0000
|
||||||
|
CTRL_REG2 uint8 = 0x21
|
||||||
|
// CTRL_REG3 (0x22)
|
||||||
|
// ====================================================================
|
||||||
|
// BIT Symbol Description Default
|
||||||
|
// --- ------ --------------------------------------------- -------
|
||||||
|
// 7 I1_Int1 Interrupt enable on INT1 (0=disable,1=enable) 0
|
||||||
|
// 6 I1_Boot Boot status on INT1 (0=disable,1=enable) 0
|
||||||
|
// 5 H-Lactive Interrupt active config on INT1 (0=high,1=low) 0
|
||||||
|
// 4 PP_OD Push-Pull/Open-Drain (0=PP, 1=OD) 0
|
||||||
|
// 3 I2_DRDY Data ready on DRDY/INT2 (0=disable,1=enable) 0
|
||||||
|
// 2 I2_WTM FIFO wtrmrk int on DRDY/INT2 (0=dsbl,1=enbl) 0
|
||||||
|
// 1 I2_ORun FIFO overrun int on DRDY/INT2 (0=dsbl,1=enbl) 0
|
||||||
|
// 0 I2_Empty FIFI empty int on DRDY/INT2 (0=dsbl,1=enbl) 0
|
||||||
|
CTRL_REG3 uint8 = 0x22
|
||||||
|
// CTRL_REG4 (0x23)
|
||||||
|
// ====================================================================
|
||||||
|
// BIT Symbol Description Default
|
||||||
|
// --- ------ --------------------------------------------- -------
|
||||||
|
// 7 BDU Block Data Update (0=continuous, 1=LSB/MSB) 0
|
||||||
|
// 6 BLE Big/Little-Endian (0=Data LSB, 1=Data MSB) 0
|
||||||
|
// 5-4 FS1/0 Full scale selection 00
|
||||||
|
// 00 = 250 dps
|
||||||
|
// 01 = 500 dps
|
||||||
|
// 10 = 2000 dps
|
||||||
|
// 11 = 2000 dps
|
||||||
|
// 0 SIM SPI Mode (0=4-wire, 1=3-wire) 0
|
||||||
|
CTRL_REG4 uint8 = 0x23
|
||||||
|
// CTRL_REG5 (0x24)
|
||||||
|
// ====================================================================
|
||||||
|
// BIT Symbol Description Default
|
||||||
|
// --- ------ --------------------------------------------- -------
|
||||||
|
// 7 BOOT Reboot memory content (0=normal, 1=reboot) 0
|
||||||
|
// 6 FIFO_EN FIFO enable (0=FIFO disable, 1=enable) 0
|
||||||
|
// 4 HPen High-pass filter enable (0=disable,1=enable) 0
|
||||||
|
// 3-2 INT1_SEL INT1 Selection config 00
|
||||||
|
// 1-0 OUT_SEL Out selection config 00
|
||||||
|
CTRL_REG5 uint8 = 0x24
|
||||||
|
REFERENCE uint8 = 0x25
|
||||||
|
OUT_TEMP uint8 = 0x26
|
||||||
|
STATUS_REG uint8 = 0x27
|
||||||
|
OUT_X_L uint8 = 0x28
|
||||||
|
OUT_X_H uint8 = 0x29
|
||||||
|
OUT_Y_L uint8 = 0x2A
|
||||||
|
OUT_Y_H uint8 = 0x2B
|
||||||
|
OUT_Z_L uint8 = 0x2C
|
||||||
|
OUT_Z_H uint8 = 0x2D
|
||||||
|
FIFO_CTRL_REG uint8 = 0x2E
|
||||||
|
FIFO_SRC_REG uint8 = 0x2F
|
||||||
|
INT1_CFG uint8 = 0x30
|
||||||
|
INT1_SRC uint8 = 0x31
|
||||||
|
INT1_TSH_XH uint8 = 0x32
|
||||||
|
INT1_TSH_XL uint8 = 0x33
|
||||||
|
INT1_TSH_YH uint8 = 0x34
|
||||||
|
INT1_TSH_YL uint8 = 0x35
|
||||||
|
INT1_TSH_ZH uint8 = 0x36
|
||||||
|
INT1_TSH_ZL uint8 = 0x37
|
||||||
|
INT1_DURATION uint8 = 0x38
|
||||||
|
)
|
||||||
+14
-12
@@ -14,18 +14,12 @@ type Device struct {
|
|||||||
Address uint8
|
Address uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connected returns whether LPS22HB has been found.
|
// New creates a new LPS22HB connection. The I2C bus must already be
|
||||||
// It does a "who am I" request and checks the response.
|
// configured.
|
||||||
func (d *Device) Connected() bool {
|
//
|
||||||
data := []byte{0}
|
// This function only creates the Device object, it does not touch the device.
|
||||||
d.bus.ReadRegister(d.Address, LPS22HB_WHO_AM_I_REG, data)
|
func New(bus drivers.I2C) Device {
|
||||||
return data[0] == 0xB1
|
return Device{bus: bus, Address: LPS22HB_ADDRESS}
|
||||||
}
|
|
||||||
|
|
||||||
// Configure sets up the LPS22HB device for communication.
|
|
||||||
func (d *Device) Configure() {
|
|
||||||
// set to block update mode
|
|
||||||
d.bus.WriteRegister(d.Address, LPS22HB_CTRL1_REG, []byte{0x02})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPressure returns the pressure in milli pascals (mPa).
|
// ReadPressure returns the pressure in milli pascals (mPa).
|
||||||
@@ -42,6 +36,14 @@ func (d *Device) ReadPressure() (pressure int32, err error) {
|
|||||||
return int32(pValue * 1000), nil
|
return int32(pValue * 1000), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connected returns whether LPS22HB 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, LPS22HB_WHO_AM_I_REG, data)
|
||||||
|
return data[0] == 0xB1
|
||||||
|
}
|
||||||
|
|
||||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||||
d.waitForOneShot()
|
d.waitForOneShot()
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ package lps22hb
|
|||||||
|
|
||||||
import "tinygo.org/x/drivers"
|
import "tinygo.org/x/drivers"
|
||||||
|
|
||||||
// New creates a new LPS22HB connection. The I2C bus must already be
|
// Configure sets up the LPS22HB device for communication.
|
||||||
// configured.
|
func (d *Device) Configure() {
|
||||||
//
|
// set to block update mode
|
||||||
// This function only creates the Device object, it does not touch the device.
|
d.bus.WriteRegister(d.Address, LPS22HB_CTRL1_REG, []byte{0x02})
|
||||||
func New(bus drivers.I2C) Device {
|
|
||||||
return Device{bus: bus, Address: LPS22HB_ADDRESS}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user