Compare commits

...

166 Commits

Author SHA1 Message Date
deadprogram 91909cf84a lorawan: increment devnonce don't just create a new one each join attempt
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-16 00:18:38 +01:00
deadprogram 8ff5e7095e sx126x: actually set the frequency when calling SetFrequency()
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 23:10:31 +01:00
deadprogram b0286910c4 lorawan: increment devnonce don't just create a new one each join attempt
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 21:28:30 +01:00
deadprogram 2bb10bf6b9 lorawan: simplify GetRand16() function
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 632cc964d5 lorawan: set devNonce to new random value on each attempt to join
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram e296fa822b lorawan: increase timeout values for tx/rx
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram d09ee42742 examples: set pin mappings for sx126x external board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 10458f377f sx126x: pre-define all errors to avoid heap allocations
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 2174b039a5 sx126x: move RadioController into separate file for clarity
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 23b0068e53 sx126x: correct RX/TX pin mapping for TheThingsIndustries GNSE board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 7372929a35 sx126x: there is no dio0 just dio1
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 68b1b14347 sx126x: refactor to RadioController interface to more easily handle non-STM32WL boards and remove duplicated code
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram 1ba616c6a6 lora/lorawan: set functions for keys
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram c149f3d458 examples: lorawan atcmd outputs needed info after Join to reuse, aka 'OTAA provisioning'
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram b096e7f2db lora/lorawan: completed functions needed for Join OTAA process
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-15 19:29:50 +01:00
deadprogram ae2c06592d gps: improve error handling
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-14 13:27:08 +01:00
deadprogram da791bf9f4 gps: add support for GLL sentence type, add original sentence to gps errors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-14 12:32:45 +01:00
deadprogram c1637d0b79 gps: improve error handling
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-14 11:15:12 +01:00
sago35 999f42dc03 net/http: add PostForm() 2023-01-11 21:29:12 +01:00
Olivier Fauchon a1b47cd778 lorawan: Add test in Makefile 2023-01-11 07:48:30 +01:00
Olivier Fauchon 889536f7f0 Lorawan uplink support and new lorawan 'basic-demo' example 2023-01-11 07:48:30 +01:00
deadprogram 301e6bc35b examples: improvements to README for LoRaWAN atcmd example
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-10 22:45:01 +01:00
deadprogram 49b390f7bc examples: lorawan atcmd able to join
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-10 22:45:01 +01:00
deadprogram a62fc01d81 lora/lorawan: implement minimal Join() function, and supporting functions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-10 22:45:01 +01:00
deadprogram 36dfdf568e examples: move atcmd into lorawan
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-10 22:45:01 +01:00
deadprogram 7b5a3970ca lorawan: add initial LoRaWAN stack support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-10 22:45:01 +01:00
deadprogram 3433364586 examples: example with LoRa AT command set implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-10 22:45:01 +01:00
deadprogram 338be928c9 sx126x, sx127x: remove extra Lora in functions to avoid stuttering
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-09 07:36:07 +01:00
deadprogram 98943393a5 sx127x: correct header type implicit/explcit as they were reversed
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-09 07:36:07 +01:00
deadprogram 6b817faed3 sx126x: add Reset() and needed pin
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-09 07:36:07 +01:00
deadprogram 9b14ee3ec5 sx127x: lora rx/tx example working, now assumes pybadge+featherwing
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-09 07:36:07 +01:00
deadprogram 6d51370512 lora: created shared RadioEvent
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-09 07:36:07 +01:00
deadprogram 2005d7d483 lora: move shared config for sx126x/sx127x to single package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-09 07:36:07 +01:00
Olivier Fauchon f15eec822f sx127x: Ajout du support d'interruptions RXTimeout (DIO1) 2023-01-09 07:36:07 +01:00
Olivier Fauchon dc4f0c974a sx127x: Major cleanup/rewrite, and tests pass with lorawan stack tests 2023-01-09 07:36:07 +01:00
Olivier Fauchon 28ddb2681d sx127x: Driver for Semtech sx127x radio modules
This first version of the driver has been tested with BB-FRM9x module
2023-01-09 07:36:07 +01:00
BCG 877342d0ff add suport for SH1106 display driver 2022-12-23 09:30:37 +01:00
deadprogram 8b3075fdba build: remove older format build tags
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-12-21 17:47:14 -05:00
Kenneth Bell 7d58709b7d bme280: improve config support 2022-12-20 11:13:43 +01:00
Jason Del Ponte 789bbbd89f Update DHT22 receive to use runtime/interrupt
Fixes #483 by updating the DHT22 device to use runtime/interrupt instead
of machine.UART1 for interrupt disabling while receiving signals from the
device.
2022-12-20 11:10:52 +01:00
Lucas Bremgartner ea944c8933 buzzer: no tone during rest 2022-12-19 22:01:39 +01:00
Lucas Bremgartner d27859453c buzzer: make all note durations float64 2022-12-19 22:01:39 +01:00
Damian Gryski 0ccd979f23 examples: fix odd if sequence found by static analysis 2022-12-04 21:26:47 +01:00
John Clark a888570c8c fix broken link for lora sx1261 2022-11-23 22:13:43 +01:00
Michael Meister 5b2c2f800d vl53l1x: Add getter for the effective SPAD count
Implement function to get the effective SPAD count.

Signed-off-by: Michael Meister <michael.meister@bytesatwork.ch>
2022-11-15 17:58:24 +01:00
Scott Feldman 0ec887c9d8 wifinina: add support for http server (#480)
* wifinina: add support for http server

This adds http.ListenAndServe() implementation for wifinina.  Included
is an example webserver, basically copied from the rtl8720dn/webserver.

Tested on Arduino Nano RP2040 Connect.  Also tried testing on Arduino
Nano33 IoT but test panics with "out of memory".  There's only 32K of
SRAM on the Nano33, vs 264K on the rp2040 Connect.
2022-11-14 22:24:15 +01:00
Lucas Bremgartner c5dbe18be1 lsm303agr: fix I2C address auto increment for multi data read
fixes: #475
2022-10-31 10:02:44 +01:00
Andy Janata 2bca84b8d1 remove unused import 2022-10-29 23:39:52 +02:00
Lucas Bremgartner 690daebcd1 microbitmatrix: add smoke test for microbitmatrix with microbit-v2 2022-10-29 22:49:31 +02:00
Lucas Bremgartner 89770a7d05 microbitmatrix: add support for brightness of led pixels
Inspired by brightness levels in micro:bit MicroPython
2022-10-29 22:49:31 +02:00
Lucas Bremgartner 8a39bb7aae microbitmatrix: harmonize v1 and v2 implementation 2022-10-29 22:49:31 +02:00
Lucas Bremgartner a106fd48ce microbitmatrix: move Size() to verion agnostic part 2022-10-29 22:49:31 +02:00
Lucas Bremgartner b2fdd3c333 microbitmatrix: add link to schema for microbit V2 2022-10-29 22:49:31 +02:00
Ayke van Laethem 42dc6eb068 mpu6050: return I2C error when configuring fails
An I2C bus can generate errors (like any I/O can), but they weren't
returned. This commit fixes this oversight.

Found while trying to figure out why LLVM 15 is broken just for the
itsybitsy-m4.
2022-10-18 20:32:33 +02:00
Rafael Badiale c00cb3abdd qmi8658c: Add support for the QMI8658C sensor (#467)
* Add support for the QMI8658C sensor

* qmi8656c: update ReadTemperature signature

* Update README devices count
2022-10-02 14:14:37 +02:00
deadprogram 81bc1bcad1 all: prepare for release 0.23.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-10-01 23:07:23 +02:00
deadprogram 1bb1b621c6 all: correct go fmt
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-25 13:23:16 +02:00
Lucas Bremgartner 98ba5a231a microbitmatrix: fix inverted axis
Resolves #460
2022-09-24 13:19:37 +02:00
sago35 5af2512901 espat,wifinina,rtl8720dn: change ssid/pass from const to var 2022-09-24 11:34:29 +02:00
Lucas Matte 4061adf6db Add GC9A01 Driver (#452)
* Added driver for gc9a01 round display and example code
2022-09-18 15:22:07 +02:00
Alexandre Jomin 7133c2e9db feat(ssd1306): add getter method to the current buffer 2022-09-16 18:51:10 +02:00
deadprogram 0ea72e7f1e makeybutton: revise to better match the algorithm defined by the original
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-16 18:34:36 +02:00
sago35 7396a5be43 examples/rtl8720dn: remove wifi setting 2022-09-06 13:51:46 +02:00
deadprogram c409e8f3cf examples/rtl8720dn: add call to optional debug setting
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-06 13:29:15 +02:00
deadprogram a6a8d478b9 examples/rtl8720dn: update all remaining examples for refactored API
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-06 13:29:15 +02:00
deadprogram 54ddb895cc rtl8720dn: refactor by bringing this driver more in line with wifinina and espat
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-06 13:29:15 +02:00
Daniel Esteban 6f05615f3e Initial support for VL6180x sensor
required changes
2022-09-05 16:04:30 +02:00
Arsen6331 2a2e897261 Trim quotes from IP returned by espat's GetDNS() 2022-08-19 18:55:09 +02:00
deadprogram ce0ce03cfe all: release 0.22.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-08-16 11:43:34 +02:00
jmacwhyte 5bd814c9de MQTT: adds keepalive pinging, disconnect, and graceful goroutine cleanup 2022-08-10 19:23:36 +02:00
sago35 41b7f06d05 rtl8720dn: add UDP close function 2022-08-08 08:43:57 +02:00
Kenneth Bell 749b2f6726 epd: add waveshare 2.9in (v1) 2022-08-05 21:01:04 +02:00
deadprogram 71c77d4b53 makeybutton: move pin config where it needs to be
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-28 08:31:53 +02:00
deadprogram 1f54c7dd23 makeybutton: use smaller buffer for faster response
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-28 08:31:53 +02:00
deadprogram d0163c67f5 all: update tinyfont to v0.3.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-25 17:38:48 +02:00
deadprogram 80cd4d9dac all: update tinyfs to v0.2.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-24 17:05:01 +02:00
sago35 594ba1dab2 net/http: support for cookies when https 2022-07-24 16:13:18 +02:00
sago35 625c565c0b rtl8720dn: improve error handling 2022-07-24 12:21:50 +02:00
sago35 b64d4ec3a0 net/http: improve header parsing 2022-07-24 12:09:06 +02:00
sago35 171366698b net/http: Fix http.Get() with port specification 2022-07-23 09:13:55 +02:00
jmacwhyte ca34b93e5d add last-will-and-testament to MQTT 2022-07-22 13:40:44 +02:00
Kamil Wcisło 2cfc08b560 net/mqtt: add support for retained messsages 2022-07-21 13:00:08 +02:00
sago35 1850c5effb rtl8720dn: add ./examples/rtl8720dn/version 2022-07-20 11:38:07 +02:00
Neil Davis 810888ce42 Makefile recursively finds unit-tests
This commit modifies how the Makefile selects dirs for the unit-test target
Instead of assuming all dirs have tests and manually excluding those that don't,
it now recursively finds all dirs containing files with names matching "*_test.go"

A manual exclusion list is maintained for operational use.
2022-07-19 11:58:37 +02:00
deadprogram cafe8df620 makeybutton: add driver for MakeyMakey-like button
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-18 20:44:46 +02:00
Neil Davis 13c43350a3 Fix irremote reporting incorrect NEC addresses and command codes (#422)
Change from reading MSB->LSB to LSB->MSB
Fixes https://github.com/tinygo-org/drivers/issues/422
2022-07-13 12:07:44 +02:00
deadprogram 3edd8e413b build: switching to GHA
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-12 00:15:33 +02:00
deadprogram 159f13974c all: update for release v0.21.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-05 11:15:55 +02:00
Neil Davis 8ddcd69ac0 Add support for '8-step mode' to easystepper
Currently, easystepper driver supports only '4-step mode' (12-23-34-41) when energizing the coils
This does not work with all motors & drivers (e.g. 28BJY-48 & ULN2003)

This commit adds support for 8-step mode (1-12-2-23-3-34-4-41)

Note: this commit breaks backward source compatibility for the factory/constructor functions.
2022-06-12 22:19:42 +02:00
deadprogram 1c038f5183 wifinina: add mutex to prevent communication race problems
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-06-11 10:59:41 +02:00
tgilkerson 36a8b791dc fix(ssd1351): Fix mirrored text on OLED display 2022-06-04 09:13:44 +02:00
Olaf Flebbe df0d0d29a4 ws2812: support thingplus-rp2040 board
Added 125 MHz rp2040 timing
  Added unsafe.Pointer for pointer conversion
2022-05-28 10:22:26 +02:00
Yurii Soldak 3bdab45452 lsm6ds3tr: initial implementation 2022-05-27 07:48:50 +02:00
Olaf Flebbe 9f6783670f sdcard: support thingplus-rp2040
The instances of SPI interfaces SPI0, SPI1, ... are
pointers to SPI types on rp2040 machines, rather plain
values like other machines.

This needs restructuring the sdcard API to take a pointer
to the SPI interface rather the SPI type itself.

Removed waitserial() since it needs modem control lines
not available on most boards
2022-05-24 19:16:34 +02:00
Daniel Esteban ec00fdef9b initial support for UC8151 driver, used in Pimoroni's badger2040 e-paper (#416) 2022-05-24 17:43:07 +02:00
Michael Meister e4951091f4 vl53l1x: Add functions for setting the device address
Implement functions to get and set the device address similar to its
reference implementation in C:
https://github.com/pololu/vl53l1x-arduino/blob/master/VL53L1X.cpp#L28

Signed-off-by: Michael Meister <michael.meister@bytesatwork.ch>
2022-05-18 19:43:30 +02:00
Daniel Esteban 19caee9b76 fixed link to datasheet
fixed temp/humidity values
2022-05-15 07:41:39 +02:00
deadprogram c235509580 scd4x: implement driver for CO2 sensor
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-05-15 07:41:39 +02:00
deadprogram dbff576c9e all: release 0.20.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-28 17:03:38 +02:00
Ayke van Laethem f0a260be66 ws2812: convert AVR assembly to C inline assembly
See https://github.com/tinygo-org/drivers/pull/401 for details.
I haven't converted it to autogenerated assembly because AVR is
different from many other architectures (8-bit, among others) and it
didn't seem worth the effort as many chips run at 16MHz anyway.

I ran the two AVR smoke tests for the ws2812 driver and the resulting
binary is exactly the same.
2022-04-21 11:10:18 +02:00
Ayke van Laethem 06e298c514 ws2812: write inline assembly using C instead of Go
This is better for various reasons:

  * I don't like the inline assembly implementation in TinyGo. It kinda
    works, but it's hard to use correctly.
  * The Go version had a subtle bug: the i and value variables weren't
    marked as modified. The compiler produced correct code by chance. In
    GCC-style inline assembly, it's possible to correctly mark it as an
    input+output operand.
  * LLVM 14 has some changes to inline assembly that change how memory
    operands can be created. Instead of supporting that, I'd like to get
    rid of memory operands entirely (and possibly inline assembly in
    general).

I did some light testing: the ARM assembly changed a bit but not in any
way that should have a practical effect, and the RISC-V assembly didn't
change at all.
2022-04-21 11:10:18 +02:00
Kuiki f2f470973d fix esp8266 ConnectToAccessPoint timeout args 2022-04-21 10:23:21 +02:00
Oliver Stäbler 448598cbf8 vl53l1x: Add functions for setting 'region of interest'
Implement functions to get and set 'region of interest' similar to its
reference implementation in C:
https://github.com/pololu/vl53l1x-arduino/commit/a6de3966784aa07680bb35a1f9ac369959efe19f

Signed-off-by: Oliver Stäbler <oliver.staebler@bytesatwork.ch>
2022-04-21 08:03:22 +02:00
Oliver Stäbler ec98f2dc2c vl53l1x: Fix switch-case semantics
The source code has been ported from C. It seems, the different
semantics of switch-case in Go has not been ported properly.
To fix this, remove 'break' statements and introduce 'fallthrough' where
necessary.

Signed-off-by: Oliver Stäbler <oliver.staebler@bytesatwork.ch>
2022-04-20 20:14:36 +02:00
Patricio Whittingslow 2476cd7bd8 pca9685: fix on=0 bug
Setting on to zero caused PWM signal to be set to high.
2022-04-16 19:14:01 +02:00
Neil Davis 01fed475e1 Add 'irremote' package as a basic infra-red driver
Currently contains an IR Receiver device only.
An IR Sender device will be added shortly

Supports receiving only NEC (extended address) protocol including repeat codes so far
2022-04-11 22:05:57 +02:00
soypat edfdd4e09e add l3gd20 gyro driver 2022-04-08 15:41:46 +02:00
soypat 5e54f08605 pca9685: add buffered one shot write 2022-04-04 17:12:39 +02:00
sago35 880b958d64 ili9341: added Feather board support to InitDisplay() 2022-03-12 08:42:26 +01:00
sago35 24db8b4e2c ili9341: add support for atsame5x 2022-03-11 07:53:30 +01:00
sago35 6df9247f92 ili9341: avoid heap allocations 2022-03-10 20:28:20 +01:00
Elfo404 56fb346438 dht: fix error check in example 2022-03-10 19:10:50 +01:00
Neil Davis 3d279d4d25 Add a SetIntensity() function to max7xx driver and example.
Also remove redundant byte() casts from SetScanLimit()
2022-03-10 18:05:34 +01:00
sago35 4a336f674c image: fix interface 2022-03-10 12:53:44 +01:00
Ayke van Laethem 2d32995f6a ws2812: support high-MHz ARMv6M chips like the RP2040
The possible branch distance is a lot shorter on ARMv6M (Cortex-M and
Cortex-M0+) for conditional branches. Therefore, convert this long
conditional branch into an unconditional branch.

This probably makes the code a little bit slower but because it is in
the low period of the WS2812 signal it shouldn't matter for the
protocol. And it avoids difficult workarounds specifically for the
RP2040.
2022-03-10 10:50:12 +01:00
Anton Fisher 9a98d1be55 drivers: add driver for IS31FL3731 matrix LED driver (#370)
IS31FL3731: add driver for IS31FL3731 matrix LED driver
2022-03-09 13:54:07 +01:00
Donia Chaiehloudj 02e4548966 dht: fix humidity and temperature extraction for DHT22 (#358) 2022-03-08 12:42:28 +01:00
Yurii Soldak 45dce188f5 lsmXXX: unified, error handling, memory management 2022-02-18 06:10:27 +01:00
Steven Pearson b3c0315a09 Driver for SSD1289 LCD 2022-02-18 06:01:55 +01:00
BCG 0ced12683c Revert "Added support for 125MHz to WS2812 for RP2040"
This reverts commit b4eb406a43 (erroneous
push).
2022-02-14 01:06:23 -05:00
BCG b4eb406a43 Added support for 125MHz to WS2812 for RP2040 2022-02-14 00:48:33 -05:00
sago35 10bd48c39d ws2812: add support for m5stamp-c3 2022-02-11 23:47:55 +01:00
Yurii Soldak ad3ef92cfe lps22hb: pin rename, sync with main repo 2022-01-29 23:02:42 +01:00
deadprogram f7dce6ae22 wifinina: correct sendParamStr to handle empty strings, such as when connecting to an unsecured access point.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-26 23:05:50 +01:00
deadprogram a15f2167cc release: prepare for v0.19.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-26 18:26:16 +01:00
deadprogram 5d5378a47c all: update license year to 2022
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-26 18:25:15 +01:00
deadprogram 3ceb688663 examples/wifi: add unified example for tcpclient that compiles for all supported wifi adaptors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-24 13:24:39 +01:00
deadprogram 941c1c9057 wifi/espat, rtl8720dn, wifinina, net: modify to use Adapter interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-24 13:24:39 +01:00
deadprogram d8c813d515 wifi/espat, rtl8720dn, wifinina: move towards standard common interface for wifi adaptors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-24 13:24:39 +01:00
Drayton Munster 905fc6fce3 hd44780: fix 4-bit data length flag 2022-01-20 20:01:37 +01:00
Drayton Munster 80913d5fe7 Reset data pins to output mode after reading 2022-01-20 20:01:37 +01:00
Olivier Fauchon b6c750ccd1 sx126x: Driver for Semtech sx126x radio modules and optional RF Switch.
This first version of the driver has been tested with STM32WL SoC,
	which embeddeds SX1262 radio on the same die.
2022-01-15 17:22:36 +01:00
deadprogram 43899e1330 build: remove smoketest for Arduino keyboard4x4 for now
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-12 18:26:10 +01:00
sago35 45c68ef0fc ft6336: add support for ft6336 2022-01-04 15:54:35 +01:00
Olivier Fauchon 025a66655f shtc3: Sensirion SHTC3 Relative Humidity / Temperature i2c sensor 2021-12-28 16:02:10 +01:00
deadprogram 121e8147f7 hd44780i2c: clean up for go fmt
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-24 16:00:39 +01:00
Alan Wang b48bc5ac5d Update hd44780i2c.go 2021-12-24 11:54:00 +01:00
Alan Wang 0d40c99d1f Add files via upload 2021-12-22 16:49:54 +01:00
Alan Wang bee7422c3a Fix Nano 33 BLE drivers (#351)
Fix HTS221, LPS22HB and APDS9960 drivers and their examples for Arduino Nano 33 BLE:

* Update hts221_nano_33_ble.go
* Update lps22hb_nano_33_ble.go
* Update apds9960_nano_33_ble.go
2021-12-20 09:57:37 +01:00
spearson78 43099c5d5f XPT2046 Touch driver (#350)
Co-authored-by: Steven Pearson <steven.pearson.78@gmail.com>
2021-12-14 09:14:10 +09:00
Yurii Soldak 0f9b9d873b wifinina: avoid busy wait 2021-12-10 12:15:56 +01:00
sago35 114e24870e ili9341, ili9342: add support for m5stack 2021-11-27 13:03:07 +01:00
soypat b33c84ff78 add PCA9685 driver 2021-11-21 14:46:15 +01:00
sago35 966210f1b0 ili9341, ili9342: add support for m5stack-core2 2021-11-20 12:20:34 +01:00
deadprogram 90a13a697b release: prepare for v0.18.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-18 15:25:24 +01:00
deadprogram d632eb888f docs: add LSM9DS1 to list
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-18 11:39:27 +01:00
Yurii Soldak f6761a9079 lsm9ds1: minimal implementation 2021-11-18 11:36:16 +01:00
sago35 51c3aa271b axp192: add support for AXP192 single Cell Li-Battery and power system management IC 2021-11-18 11:18:30 +01:00
soypat 520234e9f8 mcp3008: fix bitshift bug 2021-11-14 18:10:48 +01:00
Yurii Soldak 334ed57373 wifinina: control nina pins, for example leds 2021-11-12 15:32:21 +01:00
Sam Lader 3637033fec Fix broken link for SHT3x datasheet (#327)
docs: fix broken link for SHT3x datasheet
2021-11-06 21:26:08 +01:00
deadprogram 233866443c docs: update list of supported drivers with recent additions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-06 18:34:08 +01:00
Alan Wang 65fd7aa1a1 Add support for APDS-9960, Digital Proximity, Ambient Light, RGB and Gesture Sensor (#308)
apds9960: add support for apds9960
2021-11-06 11:22:39 +01:00
Alan Wang 82e9e4a7f3 Add support for LPS22HB MEMS nano pressure sensor (#297)
lps22hb: add support for lps22hb
2021-11-06 11:14:21 +01:00
deadprogram 76ff632134 hts221: update build tags for Go 1.17+
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-06 11:05:25 +01:00
Alan Wang cd2694e85f Add support for HTS221 capacitive digital sensor for relative humidity and temperature (#295)
hts221: Add support for hts221.go
2021-11-06 11:02:30 +01:00
sago35 734adb6df8 i2csoft: fix Configure() 2021-11-04 15:02:21 +01:00
sago35 2492fcb322 i2csoft: gofmt 2021-11-04 15:02:21 +01:00
sago35 4f82c231cb i2csoft: add source code for each target 2021-11-04 15:02:21 +01:00
sago35 2c9a05a413 i2csoft: remove the return value 2021-11-04 15:02:21 +01:00
sago35 a89a26112e i2csoft: fix baudrate handling 2021-11-04 15:02:21 +01:00
sago35 bd42656644 i2csoft: add support for software I2C 2021-11-04 15:02:21 +01:00
Ayke van Laethem 94729a4f7d ws2812: add support for RISC-V
This commit adds support for two new chips using the RISC-V
architecture: the FE310 (used in the HiFive 1) and the ESP32-C3 from
Espressif.
2021-11-03 19:14:32 +01:00
Ayke van Laethem 050cf4dbbc ws2812: make assembly generator architecture independent 2021-11-03 19:14:32 +01:00
sago35 49c8810432 ili9341: refactor examples/ili9341 2021-10-31 20:12:50 +01:00
Yurii Soldak 4b38841f71 net: fix raddr of tcp conn 2021-10-26 11:22:45 +02:00
351 changed files with 19972 additions and 3404 deletions
-20
View File
@@ -1,20 +0,0 @@
# Golang CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-go/ for more details
version: 2
jobs:
build:
docker:
- image: tinygo/tinygo-dev
steps:
- checkout
- run: tinygo version
- run:
name: "Enforce Go Formatted Code"
command: make fmt-check
- run:
name: "Run unit tests"
command: make unit-test
- run:
name: "Run build and smoke tests"
command: make smoke-test
+25
View File
@@ -0,0 +1,25 @@
name: Build
on:
pull_request:
push:
branches:
- dev
- release
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
container: tinygo/tinygo-dev
steps:
- name: Checkout
uses: actions/checkout@v2
- name: TinyGo version check
run: tinygo version
- name: Enforce Go Formatted Code
run: make fmt-check
- name: Run unit tests
run: make unit-test
- name: Run build and smoke tests
run: make smoke-test
+186
View File
@@ -1,3 +1,189 @@
0.23.0
---
- **new devices**
- Add GC9A01 Driver (#452)
- Initial support for VL6180x sensor
- **enhancements**
- **rtl8720dn**
- refactor by bringing this driver more in line with wifinina and espat
- **ssd1306**
- add getter method to the current buffer
- **makeybutton**
- revise to better match the algorithm defined by the original
- **espat,wifinina,rtl8720dn**
- change ssid/pass from const to var
- **bugfixes**
- **microbitmatrix**
- fix inverted axis
- **espat**
- Trim quotes from IP returned by espat's GetDNS()
- **all**
- correct go fmt
- **examples**
- **rtl8720dn**
- remove wifi setting
- add call to optional debug setting
- update all remaining examples for refactored API
0.22.0
---
- **new devices**
- epd: add waveshare 2.9in (v1)
- makeybutton: add driver for MakeyMakey-like button
- **enhancements**
- **rtl8720dn**
- add UDP close function
- improve error handling
- **net/http**
- improve header parsing
- add last-will-and-testament to MQTT
- **net/mqtt**
- adds keepalive pinging, disconnect, and graceful goroutine cleanup
- support for cookies when https
- add support for retained messsages
- **bugfixes**
- irremote: Fix irremote reporting incorrect NEC addresses and command codes (#422)
- net/http: Fix http.Get() with port specification
- **build**
- Makefile recursively finds unit-tests
- switching to GHA
- **updates**
- update tinyfont to v0.3.0
- update tinyfs to v0.2.0
- **examples**
- rtl8720dn: add ./examples/rtl8720dn/version
0.21.0
---
- **new devices**
- lsm6ds3tr: initial implementation
- UC8151: used in Pimoroni's badger2040 e-paper (#416)
- scd4x: implement driver for CO2 sensor
- **enhancements**
- easystepper: Add support for '8-step mode'
- vl53l1x: Add functions for setting the device address
- sdcard: support thingplus-rp2040
- wifinina: add mutex to prevent communication race problems
- **ws2812**
- support thingplus-rp2040 board
- Added 125 MHz rp2040 timing
- Added unsafe.Pointer for pointer conversion
- **bugfixes**
- ssd1351: Fix mirrored text on OLED display
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
---
- **new devices**
- apds9960: add support for APDS-9960 Digital Proximity sensor
- axp192: add support for AXP192 single Cell Li-Battery and power system management IC
- hts221: add support for HTS221 capacitive digital sensor for relative humidity and temperature
- i2csoft: add support for software I2C
- image: add support for image/jpeg and image/png
- lps22hb: add support for LPS22HB MEMS nano pressure sensor
- lsm6dox: add support for lsm6dox accelerometer
- lsm9ds1: add support for lsm9ds1 accelerometer
- **enhancements**
- ili9341: change to use drivers.SPI interface
- **ws2812**
- generate assembly instead of handwriting it
- improve timings to be compatible with the WS2811
- add support for 168MHz (e.g. Adafruit Feather STM32F405)
- add support for RISC-V
- wifinina: control nina pins, for example leds
- **docs**
- rtl8720dn: examples for tcpclient, udpstation, mqtt, and webserver
- **wifinina**
- nina-fw update docs
- examples/wifinina/http-get
- ili9341: refactor examples
- Fix broken link for SHT3x datasheet
- **core**
- all: use build directives for both Go1.17 and earlier versions
- **bugfixes**
- net: fix raddr of tcp conn
- mcp3008: fix bitshift bug
0.17.1
---
- To correct an error in the release process. Same as 0.17.0.
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018-2021 The TinyGo Authors. All rights reserved.
Copyright (c) 2018-2022 The TinyGo Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
+58 -9
View File
@@ -17,6 +17,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
@@ -51,6 +53,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/gc9a01/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
@@ -63,6 +67,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/hd44780i2c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/hts221/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hub75/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/basic
@@ -79,6 +85,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis3dh/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/lps22hb/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/lsm303agr/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
@@ -95,12 +103,16 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit-v2 ./examples/microbitmatrix/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
@@ -111,6 +123,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/shtc3/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
@@ -133,6 +147,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl53l1x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl6180x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
@@ -149,6 +165,10 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.bin -target=m5stamp-c3 ./examples/ws2812
@md5sum ./build/test.bin
tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/is31fl3731/main.go
@md5sum ./build/test.hex
ifneq ($(AVR), 0)
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/ws2812
@md5sum ./build/test.hex
@@ -181,8 +201,8 @@ endif
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go
@md5sum ./build/test.hex
# tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go
# @md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clkout/
@@ -191,6 +211,8 @@ endif
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pico ./examples/qmi8658c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
@@ -205,15 +227,42 @@ endif
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/mqttsub/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/i2csoft/adt7410/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/basic/
@md5sum ./build/test.elf
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/touchpaint/
@md5sum ./build/test.elf
tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/sx126x/lora_rxtx/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/ssd1289/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.hex -target=pico ./examples/irremote/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=badger2040 ./examples/uc8151/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/scd4x/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
@md5sum ./build/test.uf2
tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/
@md5sum ./build/test.hex
DRIVERS = $(wildcard */)
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
# rwildcard is a recursive version of $(wildcard)
# https://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
# Recursively find all *_test.go files from cwd & reduce to unique dir names
HAS_TESTS = $(sort $(dir $(call rwildcard,,*_test.go)))
# Exclude anything we explicitly don't want to test for whatever reason
EXCLUDE_TESTS = image
TESTS = $(filter-out $(addsuffix /%,$(EXCLUDE_TESTS)),$(HAS_TESTS))
unit-test:
@go test -v $(addprefix ./,$(TESTS))
@go test -v $(addprefix ./,$(TESTS))
test: clean fmt-check unit-test smoke-test
+95 -71
View File
@@ -1,6 +1,6 @@
# TinyGo Drivers
[![PkgGoDev](https://pkg.go.dev/badge/tinygo.org/x/drivers)](https://pkg.go.dev/tinygo.org/x/drivers) [![CircleCI](https://circleci.com/gh/tinygo-org/drivers/tree/dev.svg?style=svg)](https://circleci.com/gh/tinygo-org/drivers/tree/dev)
[![PkgGoDev](https://pkg.go.dev/badge/tinygo.org/x/drivers)](https://pkg.go.dev/tinygo.org/x/drivers) [![Build](https://github.com/tinygo-org/drivers/actions/workflows/build.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/drivers/actions/workflows/build.yml)
This package provides a collection of hardware drivers for devices such as sensors and displays that can be used together with [TinyGo](https://tinygo.org).
@@ -52,77 +52,101 @@ func main() {
## Currently supported devices
The following 67 devices are supported.
The following 90 devices are supported.
| Device Name | Interface Type |
|----------|-------------|
| [ADT7410 I2C Temperature Sensor](https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf) | I2C |
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
| [AHT20 I2C Temperature and Humidity Sensor](http://www.aosong.com/userfiles/files/media/AHT20%20%E8%8B%B1%E6%96%87%E7%89%88%E8%AF%B4%E6%98%8E%E4%B9%A6%20A0%2020201222.pdf) | I2C |
| [AMG88xx 8x8 Thermal camera sensor](https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf) | I2C |
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
| [BlinkM RGB LED](http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf) | I2C |
| [BME280 humidity/pressure sensor](https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf) | I2C |
| [BMI160 accelerometer/gyroscope](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi160-ds000.pdf) | SPI |
| [BMP180 barometer](https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf) | I2C |
| [BMP280 temperature/barometer](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf) | I2C |
| [BMP388 pressure sensor](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf) | I2C |
| [Buzzer](https://en.wikipedia.org/wiki/Buzzer#Piezoelectric) | GPIO |
| [DHTXX thermometer and humidity sensor](https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf) | GPIO |
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
| [HC-SR04 Ultrasonic distance sensor](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf) | GPIO |
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.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 |
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
| [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C |
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
| [MAX7219 & MAX7221 display driver](https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf) | SPI |
| [MCP23017 port expander](https://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf) | I2C |
| [MCP3008 analog to digital converter (ADC)](http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf) | SPI |
| [MCP2515 Stand-Alone CAN Controller with SPI Interface](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Family-Data-Sheet-DS20001801K.pdf) | SPI |
| [Microphone - PDM](https://cdn-learn.adafruit.com/assets/assets/000/049/977/original/MP34DT01-M.pdf) | I2S/PDM |
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
| [RTL8720DN 2.4G/5G Dual Bands Wireless and BLE5.0](https://www.seeedstudio.com/Realtek8720DN-2-4G-5G-Dual-Bands-Wireless-and-BLE5-0-Combo-Module-p-4442.html) | UART |
| [Semihosting](https://wiki.segger.com/Semihosting) | Debug |
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
| [SPI NOR Flash Memory](https://en.wikipedia.org/wiki/Flash_memory#NOR_flash) | SPI/QSPI |
| [SPI SDCARD/MMC](https://en.wikipedia.org/wiki/SD_card) | SPI |
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |
| [SSD1351 OLED display](https://download.mikroe.com/documents/datasheets/ssd1351-revision-1.3.pdf) | SPI |
| [ST7735 TFT color display](https://www.crystalfontz.com/controllers/Sitronix/ST7735R/319/) | SPI |
| [ST7789 TFT color display](https://cdn-shop.adafruit.com/product-files/3787/3787_tft_QT154H2201__________20190228182902.pdf) | SPI |
| [Stepper motor "Easystepper" controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
| [Thermistor](https://www.farnell.com/datasheets/33552.pdf) | ADC |
| [TM1637 7-segment LED display](https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_TM1637.pdf) | I2C |
| [TMP102 I2C Temperature Sensor](https://download.mikroe.com/documents/datasheets/tmp102-data-sheet.pdf) | I2C |
| [VEML6070 UV light sensor](https://www.vishay.com/docs/84277/veml6070.pdf) | I2C |
| [VL53L1X time-of-flight distance sensor](https://www.st.com/resource/en/datasheet/vl53l1x.pdf) | I2C |
| [Waveshare 2.13" (B & C) e-paper display](https://www.waveshare.com/w/upload/d/d3/2.13inch-e-paper-b-Specification.pdf) | SPI |
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI |
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
| Device Name | Interface Type |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
| [ADT7410 I2C Temperature Sensor](https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf) | I2C |
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
| [AHT20 I2C Temperature and Humidity Sensor](http://www.aosong.com/userfiles/files/media/AHT20%20%E8%8B%B1%E6%96%87%E7%89%88%E8%AF%B4%E6%98%8E%E4%B9%A6%20A0%2020201222.pdf) | I2C |
| [AMG88xx 8x8 Thermal camera sensor](https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf) | I2C |
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
| [APDS9960 Digital proximity, ambient light, RGB and gesture sensor](https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf) | I2C |
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
| [AXP192 single Cell Li-Battery and Power System Management](https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf) | I2C |
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
| [BlinkM RGB LED](http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf) | I2C |
| [BME280 humidity/pressure sensor](https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf) | I2C |
| [BMI160 accelerometer/gyroscope](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi160-ds000.pdf) | SPI |
| [BMP180 barometer](https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf) | I2C |
| [BMP280 temperature/barometer](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf) | I2C |
| [BMP388 pressure sensor](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf) | I2C |
| [Buzzer](https://en.wikipedia.org/wiki/Buzzer#Piezoelectric) | GPIO |
| [DHTXX thermometer and humidity sensor](https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf) | GPIO |
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
| [FT6336 touch controller](https://focuslcds.com/content/FT6236.pdf) | I2C |
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
| [HC-SR04 Ultrasonic distance sensor](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf) | GPIO |
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
| [HTS221 digital humidity and temperature sensor](https://www.st.com/resource/en/datasheet/hts221.pdf) | I2C |
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
| [software I2C driver](https://www.ti.com/lit/an/slva704/slva704.pdf) | GPIO |
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
| [INA260 Volt/Amp/Power meter](https://www.ti.com/lit/ds/symlink/ina260.pdf) | I2C |
| [Infrared remote control](https://en.wikipedia.org/wiki/Consumer_IR) | GPIO |
| [IS31FL3731 matrix LED driver](https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf) | I2C |
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
| [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C |
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
| [LPS22HB MEMS nano pressure sensor](https://www.st.com/resource/en/datasheet/dm00140895.pdf) | I2C |
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
| [LSM6DSOX accelerometer](https://www.st.com/resource/en/datasheet/lsm6dsox.pdf) | I2C |
| [LSM6DS3TR accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3tr.pdf) | I2C |
| [LSM303AGR accelerometer](https://www.st.com/resource/en/datasheet/lsm303agr.pdf) | I2C |
| [LSM9DS1 accelerometer](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) | I2C |
| [Makey Button](https://makeymakey.com/) | GPIO |
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
| [MAX7219 & MAX7221 display driver](https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf) | SPI |
| [MCP2515 Stand-Alone CAN Controller with SPI Interface](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Family-Data-Sheet-DS20001801K.pdf) | SPI |
| [MCP3008 analog to digital converter (ADC)](http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf) | SPI |
| [MCP23017 port expander](https://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf) | I2C |
| [Microphone - PDM](https://cdn-learn.adafruit.com/assets/assets/000/049/977/original/MP34DT01-M.pdf) | I2S/PDM |
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
| [QMI8658C accelerometer/gyroscope](https://www.qstcorp.com/upload/pdf/202202/%EF%BC%88%E5%B7%B2%E4%BC%A0%EF%BC%89QMI8658C%20datasheet%20rev%200.9.pdf) | I2C |
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
| [RTL8720DN 2.4G/5G Dual Bands Wireless and BLE5.0](https://www.seeedstudio.com/Realtek8720DN-2-4G-5G-Dual-Bands-Wireless-and-BLE5-0-Combo-Module-p-4442.html) | UART |
| [SCD4x CO2 Sensor](https://sensirion.com/media/documents/C4B87CE6/627C2DCD/CD_DS_SCD40_SCD41_Datasheet_D1.pdf) | I2C |
| [Semihosting](https://wiki.segger.com/Semihosting) | Debug |
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
| [SH1106 OLED display](https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf) | I2C / SPI |
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
| [SHTC3 Digital Humidity Sensor (RH/T)](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHTC3_Datasheet.pdf) | I2C |
| [SPI NOR Flash Memory](https://en.wikipedia.org/wiki/Flash_memory#NOR_flash) | SPI/QSPI |
| [SPI SDCARD/MMC](https://en.wikipedia.org/wiki/SD_card) | SPI |
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |
| [SSD1351 OLED display](https://download.mikroe.com/documents/datasheets/ssd1351-revision-1.3.pdf) | SPI |
| [ST7735 TFT color display](https://www.crystalfontz.com/controllers/Sitronix/ST7735R/319/) | SPI |
| [ST7789 TFT color display](https://cdn-shop.adafruit.com/product-files/3787/3787_tft_QT154H2201__________20190228182902.pdf) | SPI |
| [Stepper motor "Easystepper" controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
| [Thermistor](https://www.farnell.com/datasheets/33552.pdf) | ADC |
| [TM1637 7-segment LED display](https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_TM1637.pdf) | I2C |
| [TMP102 I2C Temperature Sensor](https://download.mikroe.com/documents/datasheets/tmp102-data-sheet.pdf) | I2C |
| [UC8151 All-in-one driver IC for ESL](https://www.buydisplay.com/download/ic/UC8151C.pdf) | I2C |
| [VEML6070 UV light sensor](https://www.vishay.com/docs/84277/veml6070.pdf) | I2C |
| [VL53L1X time-of-flight distance sensor](https://www.st.com/resource/en/datasheet/vl53l1x.pdf) | I2C |
| [VL6180X time-of-flight distance sensor](https://www.st.com/resource/en/datasheet/vl6180x.pdf) | I2C |
| [Waveshare 2.13" (B & C) e-paper display](https://www.waveshare.com/w/upload/d/d3/2.13inch-e-paper-b-Specification.pdf) | SPI |
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 2.9" e-paper display (V1)](https://www.waveshare.com/w/upload/e/e6/2.9inch_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 GC9A01 TFT round display](https://www.waveshare.com/w/upload/5/5e/GC9A01A.pdf) | SPI |
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-connect/sx1261) | SPI |
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
## Contributing
-1
View File
@@ -1,7 +1,6 @@
// Package adt7410 provides a driver for the adt7410 I2C Temperature Sensor.
//
// Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf
//
package adt7410 // import "tinygo.org/x/drivers/adt7410"
import (
-1
View File
@@ -3,7 +3,6 @@
// Datasheet EN: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
//
// Datasheet JP: http://www.analog.com/media/jp/technical-documentation/data-sheets/ADXL345_jp.pdf
//
package adxl345 // import "tinygo.org/x/drivers/adxl345"
import "tinygo.org/x/drivers"
+467
View File
@@ -0,0 +1,467 @@
// Package apds9960 implements a driver for APDS-9960,
// a digital proximity, ambient light, RGB and gesture sensor.
//
// Datasheet: https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf
package apds9960
import (
"time"
"tinygo.org/x/drivers"
)
// Device wraps an I2C connection to a APDS-9960 device.
type Device struct {
bus drivers.I2C
Address uint8
mode uint8
gesture gestureData
}
// Configuration for APDS-9960 device.
type Configuration struct {
ProximityPulseLength uint8
ProximityPulseCount uint8
GesturePulseLength uint8
GesturePulseCount uint8
ProximityGain uint8
GestureGain uint8
ColorGain uint8
ADCIntegrationCycles uint16
LEDBoost uint16
threshold uint8
sensitivity uint8
}
// for gesture-related data
type gestureData struct {
detected uint8
threshold uint8
sensitivity uint8
gXDelta int16
gYDelta int16
gXPrevDelta int16
gYPrevDelta int16
received bool
}
// for enabling various device function
type enableConfig struct {
GEN bool
PIEN bool
AIEN bool
WEN bool
PEN bool
AEN bool
PON bool
}
// New creates a new APDS-9960 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus drivers.I2C) Device {
return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE}
}
// Connected returns whether APDS-9960 has been found.
// It does a "who am I" request and checks the response.
func (d *Device) Connected() bool {
data := []byte{0}
d.bus.ReadRegister(d.Address, APDS9960_ID_REG, data)
return data[0] == 0xAB
}
// GetMode returns current engine mode
func (d *Device) GetMode() uint8 {
return d.mode
}
// DisableAll turns off the device and all functions
func (d *Device) DisableAll() {
d.enable(enableConfig{})
d.bus.WriteRegister(d.Address, APDS9960_GCONF4_REG, []byte{0x00})
d.mode = MODE_NONE
d.gesture.detected = GESTURE_NONE
}
// SetProximityPulse sets proximity pulse length (4, 8, 16, 32) and count (1~64)
// default: 16, 64
func (d *Device) SetProximityPulse(length, count uint8) {
d.bus.WriteRegister(d.Address, APDS9960_PPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)})
}
// SetGesturePulse sets gesture pulse length (4, 8, 16, 32) and count (1~64)
// default: 16, 64
func (d *Device) SetGesturePulse(length, count uint8) {
d.bus.WriteRegister(d.Address, APDS9960_GPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)})
}
// SetADCIntegrationCycles sets ALS/color ADC internal integration cycles (1~256, 1 cycle = 2.78 ms)
// default: 4 (~10 ms)
func (d *Device) SetADCIntegrationCycles(cycles uint16) {
if cycles > 256 {
cycles = 256
}
d.bus.WriteRegister(d.Address, APDS9960_ATIME_REG, []byte{uint8(256 - cycles)})
}
// SetGains sets proximity/gesture gain (1, 2, 4, 8x) and ALS/color gain (1, 4, 16, 64x)
// default: 1, 1, 4
func (d *Device) SetGains(proximityGain, gestureGain, colorGain uint8) {
d.bus.WriteRegister(d.Address, APDS9960_CONTROL_REG, []byte{getProximityGain(proximityGain)<<2 | getALSGain(colorGain)})
d.bus.WriteRegister(d.Address, APDS9960_GCONF2_REG, []byte{getProximityGain(gestureGain) << 5})
}
// LEDBoost sets proximity and gesture LED current level (100, 150, 200, 300 (%))
// default: 100
func (d *Device) LEDBoost(percent uint16) {
var v uint8
switch percent {
case 100:
v = 0
case 150:
v = 1
case 200:
v = 2
case 300:
v = 3
}
d.bus.WriteRegister(d.Address, APDS9960_CONFIG2_REG, []byte{0x01 | v<<4})
}
// Setthreshold sets threshold (0~255) for detecting gestures
// default: 30
func (d *Device) Setthreshold(t uint8) {
d.gesture.threshold = t
}
// Setsensitivity sets sensivity (0~100) for detecting gestures
// default: 20
func (d *Device) Setsensitivity(s uint8) {
if s > 100 {
s = 100
}
d.gesture.sensitivity = 100 - s
}
// EnableProximity starts the proximity engine
func (d *Device) EnableProximity() {
if d.mode != MODE_NONE {
d.DisableAll()
}
d.enable(enableConfig{PON: true, PEN: true, WEN: true})
d.mode = MODE_PROXIMITY
}
// ProximityAvailable reports if proximity data is available
func (d *Device) ProximityAvailable() bool {
if d.mode == MODE_PROXIMITY && d.readStatus("PVALID") {
return true
}
return false
}
// ReadProximity reads proximity data (0~255)
func (d *Device) ReadProximity() (proximity int32) {
if d.mode != MODE_PROXIMITY {
return 0
}
data := []byte{0}
d.bus.ReadRegister(d.Address, APDS9960_PDATA_REG, data)
return 255 - int32(data[0])
}
// EnableColor starts the color engine
func (d *Device) EnableColor() {
if d.mode != MODE_NONE {
d.DisableAll()
}
d.enable(enableConfig{PON: true, AEN: true, WEN: true})
d.mode = MODE_COLOR
}
// ColorAvailable reports if color data is available
func (d *Device) ColorAvailable() bool {
if d.mode == MODE_COLOR && d.readStatus("AVALID") {
return true
}
return false
}
// ReadColor reads color data (red, green, blue, clear color/brightness)
func (d *Device) ReadColor() (r int32, g int32, b int32, clear int32) {
if d.mode != MODE_COLOR {
return
}
data := []byte{0, 0, 0, 0, 0, 0, 0, 0}
d.bus.ReadRegister(d.Address, APDS9960_CDATAL_REG, data[:1])
d.bus.ReadRegister(d.Address, APDS9960_CDATAH_REG, data[1:2])
d.bus.ReadRegister(d.Address, APDS9960_RDATAL_REG, data[2:3])
d.bus.ReadRegister(d.Address, APDS9960_RDATAH_REG, data[3:4])
d.bus.ReadRegister(d.Address, APDS9960_GDATAL_REG, data[4:5])
d.bus.ReadRegister(d.Address, APDS9960_GDATAH_REG, data[5:6])
d.bus.ReadRegister(d.Address, APDS9960_BDATAL_REG, data[6:7])
d.bus.ReadRegister(d.Address, APDS9960_BDATAH_REG, data[7:])
clear = int32(uint16(data[1])<<8 | uint16(data[0]))
r = int32(uint16(data[3])<<8 | uint16(data[2]))
g = int32(uint16(data[5])<<8 | uint16(data[4]))
b = int32(uint16(data[7])<<8 | uint16(data[6]))
return
}
// EnableGesture starts the gesture engine
func (d *Device) EnableGesture() {
if d.mode != MODE_NONE {
d.DisableAll()
}
d.enable(enableConfig{PON: true, PEN: true, GEN: true, WEN: true})
d.mode = MODE_GESTURE
d.gesture.detected = GESTURE_NONE
d.gesture.gXDelta = 0
d.gesture.gYDelta = 0
d.gesture.gXPrevDelta = 0
d.gesture.gYPrevDelta = 0
d.gesture.received = false
}
// GestureAvailable reports if gesture data is available
func (d *Device) GestureAvailable() bool {
if d.mode != MODE_GESTURE {
return false
}
data := []byte{0, 0, 0, 0}
// check GVALID
d.bus.ReadRegister(d.Address, APDS9960_GSTATUS_REG, data[:1])
if data[0]&0x01 == 0 {
return false
}
// get number of data sets available in FIFO
d.bus.ReadRegister(d.Address, APDS9960_GFLVL_REG, data[:1])
availableDataSets := data[0]
if availableDataSets == 0 {
return false
}
// read up, down, left and right proximity data from FIFO
var dataSets [32][4]uint8
for i := uint8(0); i < availableDataSets; i++ {
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_U_REG, data[:1])
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_D_REG, data[1:2])
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_L_REG, data[2:3])
d.bus.ReadRegister(d.Address, APDS9960_GFIFO_R_REG, data[3:4])
for j := uint8(0); j < 4; j++ {
dataSets[i][j] = data[j]
}
}
// gesture detection process
d.gesture.detected = GESTURE_NONE
for i := uint8(0); i < availableDataSets; i++ {
U := dataSets[i][0]
D := dataSets[i][1]
L := dataSets[i][2]
R := dataSets[i][3]
// if all readings fall below threshold, it's possible that
// a movement's just been made
if U < d.gesture.threshold && D < d.gesture.threshold && L < d.gesture.threshold && R < d.gesture.threshold {
d.gesture.received = true
// if there were movement in the previous step (including the last data sets)
if d.gesture.gXPrevDelta != 0 && d.gesture.gYPrevDelta != 0 {
totalX := d.gesture.gXPrevDelta - d.gesture.gXDelta
totalY := d.gesture.gYPrevDelta - d.gesture.gYDelta
// if previous and current movement are in opposite directions (pass through one led then next)
// and the difference is big enough, the gesture is recorded
switch {
case totalX < -int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_LEFT
case totalX > int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_RIGHT
case totalY > int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_DOWN
case totalY < -int16(d.gesture.sensitivity):
d.gesture.detected = GESTURE_UP
}
d.gesture.gXDelta = 0
d.gesture.gYDelta = 0
d.gesture.gXPrevDelta = 0
d.gesture.gYPrevDelta = 0
}
continue
}
// recording current movement
d.gesture.gXDelta = int16(R) - int16(L)
d.gesture.gYDelta = int16(D) - int16(U)
if d.gesture.received {
d.gesture.received = false
d.gesture.gXPrevDelta = d.gesture.gXDelta
d.gesture.gYPrevDelta = d.gesture.gYDelta
}
}
return d.gesture.detected != GESTURE_NONE
}
// ReadGesture reads last gesture data
func (d *Device) ReadGesture() (gesture int32) {
return int32(d.gesture.detected)
}
// private functions
func (d *Device) configureDevice(cfg Configuration) {
d.DisableAll() // turn off everything
// "default" settings
if cfg.ProximityPulseLength == 0 {
cfg.ProximityPulseLength = 16
}
if cfg.ProximityPulseCount == 0 {
cfg.ProximityPulseCount = 64
}
if cfg.GesturePulseLength == 0 {
cfg.GesturePulseLength = 16
}
if cfg.GesturePulseCount == 0 {
cfg.GesturePulseCount = 64
}
if cfg.ProximityGain == 0 {
cfg.ProximityGain = 1
}
if cfg.GestureGain == 0 {
cfg.GestureGain = 1
}
if cfg.ColorGain == 0 {
cfg.ColorGain = 4
}
if cfg.ADCIntegrationCycles == 0 {
cfg.ADCIntegrationCycles = 4
}
if cfg.threshold == 0 {
d.gesture.threshold = 30
}
if cfg.sensitivity == 0 {
d.gesture.sensitivity = 20
}
d.SetProximityPulse(cfg.ProximityPulseLength, cfg.ProximityPulseCount)
d.SetGesturePulse(cfg.GesturePulseLength, cfg.GesturePulseCount)
d.SetGains(cfg.ProximityGain, cfg.GestureGain, cfg.ColorGain)
d.SetADCIntegrationCycles(cfg.ADCIntegrationCycles)
if cfg.LEDBoost > 0 {
d.LEDBoost(cfg.LEDBoost)
}
}
func (d *Device) enable(cfg enableConfig) {
var gen, pien, aien, wen, pen, aen, pon uint8
if cfg.GEN {
gen = 1
}
if cfg.PIEN {
pien = 1
}
if cfg.AIEN {
aien = 1
}
if cfg.WEN {
wen = 1
}
if cfg.PEN {
pen = 1
}
if cfg.AEN {
aen = 1
}
if cfg.PON {
pon = 1
}
data := []byte{gen<<6 | pien<<5 | aien<<4 | wen<<3 | pen<<2 | aen<<1 | pon}
d.bus.WriteRegister(d.Address, APDS9960_ENABLE_REG, data)
if cfg.PON {
time.Sleep(time.Millisecond * 10)
}
}
func (d *Device) readStatus(param string) bool {
data := []byte{0}
d.bus.ReadRegister(d.Address, APDS9960_STATUS_REG, data)
switch param {
case "CPSAT":
return data[0]>>7&0x01 == 1
case "PGSAT":
return data[0]>>6&0x01 == 1
case "PINT":
return data[0]>>5&0x01 == 1
case "AINT":
return data[0]>>4&0x01 == 1
case "PVALID":
return data[0]>>1&0x01 == 1
case "AVALID":
return data[0]&0x01 == 1
default:
return false
}
}
func getPulseLength(l uint8) uint8 {
switch l {
case 4:
return 0
case 8:
return 1
case 16:
return 2
case 32:
return 3
default:
return 0
}
}
func getPulseCount(c uint8) uint8 {
if c < 1 && c > 64 {
return 0
}
return c - 1
}
func getProximityGain(g uint8) uint8 {
switch g {
case 1:
return 0
case 2:
return 1
case 4:
return 2
case 8:
return 3
default:
return 0
}
}
func getALSGain(g uint8) uint8 {
switch g {
case 1:
return 0
case 4:
return 1
case 16:
return 2
case 64:
return 3
default:
return 0
}
}
+9
View File
@@ -0,0 +1,9 @@
//go:build !nano_33_ble
package apds9960
// Configure sets up the APDS-9960 device.
func (d *Device) Configure(cfg Configuration) {
// configure device
d.configureDevice(cfg)
}
+23
View File
@@ -0,0 +1,23 @@
//go:build nano_33_ble
package apds9960
import (
"machine"
"time"
)
// Configure sets up the APDS-9960 device.
func (d *Device) Configure(cfg Configuration) {
// Following lines are Nano 33 BLE specific, they have nothing to do with sensor per se
machine.LSM_PWR.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.LSM_PWR.High()
machine.I2C_PULLUP.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.I2C_PULLUP.High()
// Wait a moment
time.Sleep(10 * time.Millisecond)
// configure device
d.configureDevice(cfg)
}
+78
View File
@@ -0,0 +1,78 @@
package apds9960
const (
// I2C address
ADPS9960_ADDRESS = 0x39
// control/status registers
APDS9960_RAM_REG = 0x00
APDS9960_ENABLE_REG = 0x80
APDS9960_ATIME_REG = 0x81
APDS9960_WTIME_REG = 0x83
APDS9960_AILTIL_REG = 0x84
APDS9960_AILTH_REG = 0x85
APDS9960_AIHTL_REG = 0x86
APDS9960_AIHTH_REG = 0x87
APDS9960_PILT_REG = 0x89
APDS9960_PIHT_REG = 0x8B
APDS9960_PERS_REG = 0x8C
APDS9960_CONFIG1_REG = 0x8D
APDS9960_PPULSE_REG = 0x8E
APDS9960_CONTROL_REG = 0x8F
APDS9960_CONFIG2_REG = 0x90
APDS9960_ID_REG = 0x92
APDS9960_STATUS_REG = 0x93
APDS9960_CDATAL_REG = 0x94
APDS9960_CDATAH_REG = 0x95
APDS9960_RDATAL_REG = 0x96
APDS9960_RDATAH_REG = 0x97
APDS9960_GDATAL_REG = 0x98
APDS9960_GDATAH_REG = 0x99
APDS9960_BDATAL_REG = 0x9A
APDS9960_BDATAH_REG = 0x9B
APDS9960_PDATA_REG = 0x9C
APDS9960_POFFSET_UR_REG = 0x9D
APDS9960_POFFSET_DL_REG = 0x9E
APDS9960_CONFIG3_REG = 0x9F
APDS9960_GPENTH_REG = 0xA0
APDS9960_GEXTH_REG = 0xA1
APDS9960_GCONF1_REG = 0xA2
APDS9960_GCONF2_REG = 0xA3
APDS9960_GOFFSET_U_REG = 0xA4
APDS9960_GOFFSET_D_REG = 0xA5
APDS9960_GOFFSET_L_REG = 0xA7
APDS9960_GOFFSET_R_REG = 0xA9
APDS9960_GPULSE_REG = 0xA6
APDS9960_GCONF3_REG = 0xAA
APDS9960_GCONF4_REG = 0xAB
APDS9960_GFLVL_REG = 0xAE
APDS9960_GSTATUS_REG = 0xAF
APDS9960_IFORCE_REG = 0xE4
APDS9960_PICLEAR_REG = 0xE5
APDS9960_CICLEAR_REG = 0xE6
APDS9960_AICLEAR_REG = 0xE7
APDS9960_GFIFO_U_REG = 0xFC
APDS9960_GFIFO_D_REG = 0xFD
APDS9960_GFIFO_L_REG = 0xFE
APDS9960_GFIFO_R_REG = 0xFF
)
const (
// sensor modes
MODE_NONE = iota
MODE_PROXIMITY
MODE_COLOR
MODE_GESTURE
)
const (
// detected gestures
GESTURE_NONE = iota
GESTURE_UP
GESTURE_DOWN
GESTURE_LEFT
GESTURE_RIGHT
)
+257
View File
@@ -0,0 +1,257 @@
// Package axp192 provides a driver for the axp192 I2C Enhanced single Cell
// Li-Battery and Power System Management IC.
//
// http://www.x-powers.com/en.php/Info/product_detail/article_id/29
// Datasheet: https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf
package axp192 // import "tinygo.org/x/drivers/axp192"
import (
"tinygo.org/x/drivers"
)
type Error uint8
const (
ErrInvalidID Error = 0x1
)
func (e Error) Error() string {
switch e {
case ErrInvalidID:
return "Invalid chip ID"
default:
return "Unknown error"
}
}
type Device struct {
bus drivers.I2C
buf []byte
Address uint8
}
// New returns AXP192 device for the provided I2C bus using default address.
func New(i2c drivers.I2C) *Device {
return &Device{
bus: i2c,
buf: make([]byte, 2),
Address: Address,
}
}
type Config struct {
}
// Configure the AXP192 device.
func (d *Device) Configure(config Config) error {
return nil
}
// ReadPowerSupplyStatus reads power supply status.
func (d *Device) ReadPowerSupplyStatus() uint8 {
return d.read8bit(RegPowerSupplyStatus)
}
// SetVbusIPSOutAccessManagement sets VBUS-IPSOUT access management.
func (d *Device) SetVbusIPSOutAccessManagement(a uint8) {
d.write1Byte(RegVbusIPSOutAccessManagement, a)
}
// GetVbusIPSOutAccessManagement gets VBUS-IPSOUT access management.
func (d *Device) GetVbusIPSOutAccessManagement() uint8 {
return d.read8bit(RegVbusIPSOutAccessManagement)
}
// SetGPIO1Control sets GPIO1 function.
func (d *Device) SetGPIO1Control(a uint8) {
d.write1Byte(RegGPIO1Control, a)
}
// GetGPIO1Control gets GPIO1 function.
func (d *Device) GetGPIO1Control() uint8 {
return d.read8bit(RegGPIO1Control)
}
// SetGPIO2Control sets GPIO2 function.
func (d *Device) SetGPIO2Control(a uint8) {
d.write1Byte(RegGPIO2Control, a)
}
// GetGPIO2Control gets GPIO2 function.
func (d *Device) GetGPIO2Control() uint8 {
return d.read8bit(RegGPIO2Control)
}
// SetGPIO20SignalStatus sets GPIO[2:0] signal status.
func (d *Device) SetGPIO20SignalStatus(a uint8) {
d.write1Byte(RegGPIO20SignalStatus, a)
}
// GetGPIO20SignalStatus gets GPIO[2:0] signal status.
func (d *Device) GetGPIO20SignalStatus() uint8 {
return d.read8bit(RegGPIO20SignalStatus)
}
// SetBackupBatteryChargingControl sets backup battery charge control.
func (d *Device) SetBackupBatteryChargingControl(a uint8) {
d.write1Byte(RegBackupBatteryChargingControl, a)
}
// GetBackupBatteryChargingControl gets backup battery charge control.
func (d *Device) GetBackupBatteryChargingControl() uint8 {
return d.read8bit(RegBackupBatteryChargingControl)
}
// SetDCDC1VoltageSet sets DC-DC1 output voltage.
func (d *Device) SetDCDC1VoltageSet(a uint8) {
d.write1Byte(RegDCDC1VoltageSet, a)
}
// GetDCDC1VoltageSet gets DC-DC1 output voltage.
func (d *Device) GetDCDC1VoltageSet() uint8 {
return d.read8bit(RegDCDC1VoltageSet)
}
// SetDCDC2VoltageSet sets DC-DC2 dynamic voltage parameter.
func (d *Device) SetDCDC2VoltageSet(a uint8) {
d.write1Byte(RegDCDC2VoltageSet, a)
}
// GetDCDC2VoltageSet gets DC-DC2 dynamic voltage parameter.
func (d *Device) GetDCDC2VoltageSet() uint8 {
return d.read8bit(RegDCDC2VoltageSet)
}
// SetDCDC3VoltageSet sets DC-DC3 output voltage.
func (d *Device) SetDCDC3VoltageSet(a uint8) {
d.write1Byte(RegDCDC3VoltageSet, a)
}
// GetDCDC3VoltageSet gets DC-DC3 output voltage.
func (d *Device) GetDCDC3VoltageSet() uint8 {
return d.read8bit(RegDCDC3VoltageSet)
}
// SetLDO23VoltageSet sets LDO2/3 output voltage.
func (d *Device) SetLDO23VoltageSet(a uint8) {
d.write1Byte(RegLDO23VoltageSet, a)
}
// GetLDO23VoltageSet gets LDO2/3 output voltage.
func (d *Device) GetLDO23VoltageSet() uint8 {
return d.read8bit(RegLDO23VoltageSet)
}
// SetDCDC13LDO23Switch sets DC-DC1/3 & LOD2/3 output control.
func (d *Device) SetDCDC13LDO23Switch(a uint8) {
d.write1Byte(RegDCDC13LDO23Switch, a)
}
// GetDCDC13LDO23Switch gets DC-DC1/3 & LOD2/3 output control.
func (d *Device) GetDCDC13LDO23Switch() uint8 {
return d.read8bit(RegDCDC13LDO23Switch)
}
// SetGPIO43FunctionControl sets GPIO[4:3] pin function.
func (d *Device) SetGPIO43FunctionControl(a uint8) {
d.write1Byte(RegGPIO43FunctionControl, a)
}
// GetGPIO43FunctionControl gets GPIO[4:3] pin function.
func (d *Device) GetGPIO43FunctionControl() uint8 {
return d.read8bit(RegGPIO43FunctionControl)
}
// SetPEKParameterSet sets PEK press key parameter.
func (d *Device) SetPEKParameterSet(a uint8) {
d.write1Byte(RegPEKParameterSet, a)
}
// GetPEKParameterSet gets PEK press key parameter.
func (d *Device) GetPEKParameterSet() uint8 {
return d.read8bit(RegPEKParameterSet)
}
// SetADCEnableSet sets ADC enable 1.
func (d *Device) SetADCEnableSet(a uint8) {
d.write1Byte(RegADCEnableSet, a)
}
// GetADCEnableSet gets ADC enable 1.
func (d *Device) GetADCEnableSet() uint8 {
return d.read8bit(RegADCEnableSet)
}
// SetGPIO43SignalStatus sets GPIO[4:3] signal status.
func (d *Device) SetGPIO43SignalStatus(a uint8) {
d.write1Byte(RegGPIO43SignalStatus, a)
}
// GetGPIO43SignalStatus gets GPIO[4:3] signal status.
func (d *Device) GetGPIO43SignalStatus() uint8 {
return d.read8bit(RegGPIO43SignalStatus)
}
// SetDCVoltage sets DC voltage.
func (d *Device) SetDCVoltage(number uint8, voltage uint16) {
if voltage < 700 {
voltage = 0
} else {
voltage = (voltage - 700) / 25
}
switch number {
case 0:
v := d.GetDCDC1VoltageSet()
d.SetDCDC1VoltageSet((v & 0x80) | (uint8(voltage) & 0x7F))
case 1:
v := d.GetDCDC2VoltageSet()
d.SetDCDC2VoltageSet((v & 0x80) | (uint8(voltage) & 0x7F))
case 2:
v := d.GetDCDC3VoltageSet()
d.SetDCDC3VoltageSet((v & 0x80) | (uint8(voltage) & 0x7F))
}
}
// SetLDOVoltage sets LDO voltage.
func (d *Device) SetLDOVoltage(number uint8, voltage uint16) {
if voltage > 3300 {
voltage = 15
} else {
voltage = (voltage / 100) - 18
}
switch number {
case 2:
v := d.GetLDO23VoltageSet()
d.SetLDO23VoltageSet((v & 0x0F) | (uint8(voltage) << 4))
break
case 3:
v := d.GetLDO23VoltageSet()
d.SetLDO23VoltageSet((v & 0xF0) | uint8(voltage))
break
}
}
// SetLDOEnable enable LDO.
func (d *Device) SetLDOEnable(number uint8, state bool) {
mark := uint8(0x01)
mark <<= number
switch number {
case 2:
v := d.GetDCDC13LDO23Switch()
d.SetDCDC13LDO23Switch(v | mark)
case 3:
v := d.GetDCDC13LDO23Switch()
d.SetDCDC13LDO23Switch(v & (^mark))
}
}
func (d *Device) write1Byte(reg, data uint8) {
d.bus.WriteRegister(d.Address, reg, []byte{data})
}
func (d *Device) read8bit(reg uint8) uint8 {
d.bus.ReadRegister(d.Address, reg, d.buf[:1])
return d.buf[0]
}
+158
View File
@@ -0,0 +1,158 @@
package axp192
import (
"time"
"tinygo.org/x/drivers"
axp192orig "tinygo.org/x/drivers/axp192"
)
// Device wraps an I2C connection to a AXP192 device.
type Device struct {
*axp192orig.Device
LED Pin
RST Pin
SPK_EN Pin
}
// New creates a new AXP192 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(i2c drivers.I2C) *Device {
d := axp192orig.New(i2c)
axp := &Device{
Device: d,
}
axp.LED = Pin{pin: 1, axp: axp}
axp.SPK_EN = Pin{pin: 2, axp: axp}
axp.RST = Pin{pin: 4, axp: axp}
axp.begin()
return axp
}
type Config struct {
}
// Configure sets up the device for communication
func (d *Device) Configure(config Config) error {
return d.Device.Configure(axp192orig.Config{})
}
func (d *Device) begin() {
d.SetVbusIPSOutAccessManagement((d.GetVbusIPSOutAccessManagement() & 0x04) | 0x02)
d.SetGPIO1Control(d.GetGPIO1Control() & 0xF8)
d.SetGPIO2Control(d.GetGPIO2Control() & 0xF8)
d.SetBackupBatteryChargingControl((d.GetBackupBatteryChargingControl() & 0x1C) | 0xA2)
d.SetESPVoltage(3350)
d.SetLcdVoltage(3300)
d.SetLDOVoltage(2, 3300) //Periph power voltage preset (LCD_logic, SD card)
d.SetLDOVoltage(3, 2000) //Vibrator power voltage preset
d.SetLDOEnable(2, true)
d.SetDCDC3(true) // LCD Backlight
// GPIO4 : LCD Reset
d.SetGPIO43FunctionControl((d.GetGPIO43FunctionControl() & 0x72) | 0x84)
// Power On/Off Setting
d.SetPEKParameterSet(0x4C)
d.SetADCEnableSet(0xFF)
d.RST.Low()
time.Sleep(100 * time.Millisecond)
d.RST.High()
time.Sleep(100 * time.Millisecond)
}
// ToggleLED toggles LED connected to AXP192.
func (d *Device) ToggleLED() {
v := d.GetGPIO20SignalStatus()
if (v & 0x02) > 0 {
d.SetGPIO20SignalStatus(v & 0xFD)
} else {
d.SetGPIO20SignalStatus(v | 0x02)
}
}
// SetESPVoltage sets voltage of ESP32.
func (d *Device) SetESPVoltage(voltage uint16) {
if voltage >= 3000 && voltage <= 3400 {
d.SetDCVoltage(0, voltage)
}
}
// SetLcdVoltage sets voltage of LCD.
func (d *Device) SetLcdVoltage(voltage uint16) {
if voltage >= 2500 && voltage <= 3300 {
d.SetDCVoltage(2, voltage)
}
}
// SetDCDC3 enables or disables DCDC3.
func (d *Device) SetDCDC3(State bool) {
v := d.GetDCDC13LDO23Switch()
if State == true {
v = (1 << 1) | v
} else {
v = ^(uint8(1) << 1) & v
}
d.SetDCDC13LDO23Switch(v)
}
// Pin is a single pin on AXP192.
type Pin struct {
pin uint8
axp *Device
}
// High sets this GPIO pin to high.
func (p Pin) High() {
switch p.pin {
case 1: // LED
v := p.axp.GetGPIO20SignalStatus()
p.axp.SetGPIO20SignalStatus(v | 0x02)
case 2: // SPK_EN
case 4: // RST
v := p.axp.GetGPIO43SignalStatus()
v |= uint8(0x02)
p.axp.SetGPIO43SignalStatus(v)
}
}
// Low sets this GPIO pin to low.
func (p Pin) Low() {
switch p.pin {
case 1: // LED
v := p.axp.GetGPIO20SignalStatus()
p.axp.SetGPIO20SignalStatus(v & 0xFD)
case 2: // SPK_EN
case 4: // RST
v := p.axp.GetGPIO43SignalStatus()
v &= ^uint8(0x02)
p.axp.SetGPIO43SignalStatus(v)
}
}
// Toggle switches an output pin from low to high or from high to low.
func (p Pin) Toggle() {
switch p.pin {
case 1: // LED
v := p.axp.GetGPIO20SignalStatus()
if (v & 0x02) == 0 {
p.axp.SetGPIO20SignalStatus(v | 0x02)
} else {
p.axp.SetGPIO20SignalStatus(v & 0xFD)
}
case 2: // SPK_EN
case 4: // RST
v := p.axp.GetGPIO43SignalStatus()
if (v & 0x02) == 0 {
v |= uint8(0x02)
} else {
v &= ^uint8(0x02)
}
p.axp.SetGPIO43SignalStatus(v)
}
}
+127
View File
@@ -0,0 +1,127 @@
package axp192
// power supply control class
// 0x00 Power supply status register
// 0x01 Power supply mode/charging status register
// 0x04 OTG VBUS status register
// 0x0609 Data buffer register
// 0x10 EXTEN & DCDC2 switch register
// 0x12 DCDC1/3 & LDO2/3switch register
// 0x23 DCDC2 voltage set register
// 0x25 DCDC2 voltage slope set register
// 0x26 DCDC1voltage set register
// 0x27 DCDC3 voltage set register
// 0x28 LDO2/3 voltage set register
// 0x30 VBUSIPSOUT access set register
// 0x31 VOFF power off voltage set register
// 0x32 Power off、battery detect、CHGLED control register
// 0x33 Charging control register1
// 0x34 Charging control register2
// 0x35 Backup battery charging control register
// 0x36 PEK parameter set register
// 0x37 DCDC switch frequency set register
// 0x38 Battery charging under temperature warning set register
// 0x39 Battery charging over temperature warning set register
// 0x3A APS under voltage Level1 set register
// 0x3B APS under voltage Level2 set register
// 0x3C Battery discharging under temperature warning set register
// 0x3D Battery discharging over temperature warning set register
// 0x80 DCDC mode set register
// 0x82 ADC enable set register 1
// 0x83 ADC enable set register 2
// 0x84 ADC sample frequency set, TS pin control register
// 0x85 GPIO [3:0] input range set register
// 0x8A Timer control register
// 0x8B VBUS monitor set register
// 0x8F Over temperature power off control register
// GPIO control class
// 0x90 GPIO0 control register
// 0x91 GPIO0 LDO mode output voltage set register
// 0x92 GPIO1 control register
// 0x93 GPIO2 control register
// 0x94 GPIO[2:0] signal status register
// 0x95 GPIO[4:3] function control register
// 0x96 GPIO[4:3] signal status register
// 0x97 GPIO[2:0] pull down control register
// 0x98 PWM1 frequency set register
// 0x99 PWM1 duty ratio set register 1
// 0x9A PWM1 duty ratio set register 2
// 0x9B PWM2 frequency set register
// 0x9C PWM2 duty ratio set register 1
// 0x9D PWM2 duty ratio set register 2
// 0x9E GPIO5 control register
// IRQ control class
// 0x40 IRQ enable control register 1
// 0x41 IRQ enable control register 2
// 0x42 IRQ enable control register 3
// 0x43 IRQ enable control register 4
// 0x44 IRQ status register 1
// 0x45 IRQ status register 2
// 0x46 IRQ status register 3
// 0x47 IRQ status register 4
// ADC data class
// 0x56 ACIN voltage ADC data high 8 bit
// 0x57 ACIN voltage ADC data low 4 bit
// 0x58 ACIN current ADC data high 8 bit
// 0x59 ACIN current ADC data low 4 bit
// 0x5A VBUS voltage ADC data high 8 bit
// 0x5B VBUS voltage ADC data low 4 bit
// 0x5C VBUS current ADC data high 8 bit
// 0x5D VBUS current ADC data low 4 bit
// 0x5E AXP192 internal temperature monitor ADC data High 8 bit
// 0x5F AXP192 internal temperature monitor ADC data low 4 bit
// 0x62 TS input ADC data High 8 bitmonitor battery temperature by default
// 0x63 TS input ADC data low 4 bitmonitor battery temperature by default
// 0x64 GPIO0 voltage ADC data high 8 bit
// 0x65 GPIO0 voltage ADC data low 4 bit
// 0x66 GPIO1 voltage ADC data high 8 bit
// 0x67 GPIO1 voltage ADC data low 4 bit
// 0x68 GPIO2 voltage ADC data high 8 bit
// 0x69 GPIO2 voltage ADC data low 4 bit
// 0x6A GPIO[3] voltage ADC data high 8 bit
// 0x6B GPIO[3] voltage ADC data low 4 bit
// 0x70 Battery instantaneous power high 8 bit
// 0x71 Battery instantaneous power middle 8 bit
// 0x72 Battery instantaneous power low 8 bit
// 0x78 Battery voltage high 8 bit
// 0x79 Battery voltage low 4 bit
// 0x7A Battery charging current high 8 bit
// 0x7B Battery charging current low 5 bit
// 0x7C Battery discharging current high 8 bit
// 0x7D Battery discharging current low 5 bit
// 0x7E APS voltage high 8 bit
// 0x7F APS voltage low 4 bit
// 0xB0 Battery charging coulomb counter data register 3
// 0xB1 Battery charging coulomb counter data register 2
// 0xB2 Battery charging coulomb counter data register 1
// 0xB3 Battery charging coulomb counter data register 0
// 0xB4 Battery discharging coulomb counter data register 3
// 0xB5 Battery discharging coulomb counter data register 2
// 0xB6 Battery discharging coulomb counter data register 1
// 0xB7 Battery discharging coulomb counter data register 0
// 0xB8 Coulomb counter control register
const (
// Address is default I2C address.
Address = 0x34
RegPowerSupplyStatus = 0x00
RegDCDC13LDO23Switch = 0x12
RegVbusIPSOutAccessManagement = 0x30
RegBackupBatteryChargingControl = 0x35
RegDCDC2VoltageSet = 0x25
RegDCDC1VoltageSet = 0x26
RegDCDC3VoltageSet = 0x27
RegLDO23VoltageSet = 0x28
RegPEKParameterSet = 0x36
RegADCEnableSet = 0x82
RegGPIO1Control = 0x92
RegGPIO2Control = 0x93
RegGPIO20SignalStatus = 0x94
RegGPIO43FunctionControl = 0x95
RegGPIO43SignalStatus = 0x96
)
-1
View File
@@ -2,7 +2,6 @@
//
// Datasheet:
// https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf
//
package bh1750 // import "tinygo.org/x/drivers/bh1750"
import (
-1
View File
@@ -1,7 +1,6 @@
// Package blinkm implements a driver for the BlinkM I2C RGB LED.
//
// Datasheet: http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf
//
package blinkm // import "tinygo.org/x/drivers/blinkm"
import "tinygo.org/x/drivers"
+117 -7
View File
@@ -3,11 +3,11 @@
//
// Datasheet:
// https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
//
package bme280
import (
"math"
"time"
"tinygo.org/x/drivers"
)
@@ -34,11 +34,27 @@ type calibrationCoefficients struct {
h6 int8
}
type Oversampling byte
type Mode byte
type FilterCoefficient byte
type Period byte
// Config contains settings for filtering, sampling, and modes of operation
type Config struct {
Pressure Oversampling
Temperature Oversampling
Humidity Oversampling
Period Period
Mode Mode
IIR FilterCoefficient
}
// Device wraps an I2C connection to a BME280 device.
type Device struct {
bus drivers.I2C
Address uint16
calibrationCoefficients calibrationCoefficients
Config Config
}
// New creates a new BME280 connection. The I2C bus must already be
@@ -52,9 +68,34 @@ func New(bus drivers.I2C) Device {
}
}
// Configure sets up the device for communication and
// read the calibration coefficientes.
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration is the Indoor Navigation settings
// from the BME280 datasheet.
func (d *Device) Configure() {
d.ConfigureWithSettings(Config{})
}
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration if config is left at defaults is
// the Indoor Navigation settings from the BME280 datasheet.
func (d *Device) ConfigureWithSettings(config Config) {
d.Config = config
// If config is not initialized, use Indoor Navigation defaults.
if d.Config == (Config{}) {
d.Config = Config{
Mode: ModeNormal,
Period: Period0_5ms,
Temperature: Sampling2X,
Humidity: Sampling1X,
Pressure: Sampling16X,
IIR: Coeff16,
}
}
var data [24]byte
err := d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION, data[:])
@@ -94,10 +135,18 @@ func (d *Device) Configure() {
d.calibrationCoefficients.h4 = 0 + (int16(h2lsb[3]) << 4) | (int16(h2lsb[4] & 0x0F))
d.calibrationCoefficients.h5 = 0 + (int16(h2lsb[5]) << 4) | (int16(h2lsb[4]) >> 4)
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{0x3f})
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{0xB7})
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{0x00})
d.Reset()
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{byte(d.Config.Period<<5) | byte(d.Config.IIR<<2)})
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{byte(d.Config.Humidity)})
// Normal mode, start measuring now
if d.Config.Mode == ModeNormal {
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
}
// Connected returns whether a BME280 has been found.
@@ -113,6 +162,20 @@ func (d *Device) Reset() {
d.bus.WriteRegister(uint8(d.Address), CMD_RESET, []byte{0xB6})
}
// SetMode can set the device to Sleep, Normal or Forced mode
//
// Calling this method is optional, Configure can be used to set the
// initial mode if no mode change is desired. This method is most
// useful to switch between Sleep and Normal modes.
func (d *Device) SetMode(mode Mode) {
d.Config.Mode = mode
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d *Device) ReadTemperature() (int32, error) {
data, err := d.readData()
@@ -149,7 +212,8 @@ func (d *Device) ReadHumidity() (int32, error) {
// ReadAltitude returns the current altitude in meters based on the
// current barometric pressure and estimated pressure at sea level.
// Calculation is based on code from Adafruit BME280 library
// https://github.com/adafruit/Adafruit_BME280_Library
//
// https://github.com/adafruit/Adafruit_BME280_Library
func (d *Device) ReadAltitude() (alt int32, err error) {
mPa, _ := d.ReadPressure()
atmP := float32(mPa) / 100000
@@ -186,6 +250,16 @@ func readIntLE(msb byte, lsb byte) int16 {
// readData does a burst read from 0xF7 to 0xF0 according to the datasheet
// resulting in an slice with 8 bytes 0-2 = pressure / 3-5 = temperature / 6-7 = humidity
func (d *Device) readData() (data [8]byte, err error) {
if d.Config.Mode == ModeForced {
// Write the CTRL_MEAS register to trigger a measurement
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
time.Sleep(d.measurementDelay())
}
err = d.bus.ReadRegister(uint8(d.Address), REG_PRESSURE, data[:])
if err != nil {
println(err)
@@ -256,3 +330,39 @@ func (d *Device) calculateHumidity(data [8]byte, tFine int32) int32 {
return int32(100 * h)
}
// measurementDelay returns how much time each measurement will take
// on the device.
//
// This is used in forced mode to wait until a measurement is complete.
func (d *Device) measurementDelay() time.Duration {
const MeasOffset = 1250
const MeasDur = 2300
const HumMeasOffset = 575
const MeasScalingFactor = 1000
// delay is based on over-sampling rate - this table converts from
// setting to number samples
sampleRateConv := []int{0, 1, 2, 4, 8, 16}
tempOsr := 16
if d.Config.Temperature <= Sampling16X {
tempOsr = sampleRateConv[d.Config.Temperature]
}
presOsr := 16
if d.Config.Temperature <= Sampling16X {
presOsr = sampleRateConv[d.Config.Pressure]
}
humOsr := 16
if d.Config.Temperature <= Sampling16X {
humOsr = sampleRateConv[d.Config.Humidity]
}
max_delay := ((MeasOffset + (MeasDur * tempOsr) +
((MeasDur * presOsr) + HumMeasOffset) +
((MeasDur * humOsr) + HumMeasOffset)) / MeasScalingFactor)
return time.Duration(max_delay) * time.Millisecond
}
+44
View File
@@ -20,6 +20,50 @@ const (
CHIP_ID = 0x60
)
// Increasing sampling rate increases precision but also the wait time for measurements. The datasheet has a table of
// suggested values for oversampling, output data rates, and iir filter coefficients by use case.
const (
SamplingOff Oversampling = iota
Sampling1X
Sampling2X
Sampling4X
Sampling8X
Sampling16X
)
// In normal mode (the default) the sensor takes masurements periodically. In forced
// mode, the sensor takes a measurement only when requested.
//
// For use-cases with infrequent sampling, forced mode is more power efficient.
const (
ModeNormal Mode = 0x03
ModeForced Mode = 0x01
ModeSleep Mode = 0x00
)
// IIR filter coefficients, higher values means steadier measurements but slower reaction times
const (
Coeff0 FilterCoefficient = iota
Coeff2
Coeff4
Coeff8
Coeff16
)
// Period of standby in normal mode which controls how often measurements are taken
//
// Note Period10ms and Period20ms are out of sequence, but are per the datasheet
const (
Period0_5ms Period = 0b000
Period62_5ms = 0b001
Period125ms = 0b010
Period250ms = 0b011
Period500ms = 0b100
Period1000ms = 0b101
Period10ms = 0b110
Period20ms = 0b111
)
const (
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
)
-1
View File
@@ -3,7 +3,6 @@
//
// Datasheet:
// https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
//
package bmp180 // import "tinygo.org/x/drivers/bmp180"
import (
+6 -1
View File
@@ -1,5 +1,4 @@
// Package buzzer provides a very simplistic driver for a connected buzzer or low-fidelity speaker.
//
package buzzer // import "tinygo.org/x/drivers/buzzer"
import (
@@ -55,6 +54,12 @@ func (l *Device) Tone(hz, duration float64) (err error) {
tempo := ((60 / l.BPM) * (duration * 1000))
// no tone during rest, just let the duration pass.
if hz == Rest {
time.Sleep(time.Duration(tempo) * time.Millisecond)
return
}
for i := 0.0; i < tempo*1000; i += tone * 2.0 {
if err = l.On(); err != nil {
return
+3 -3
View File
@@ -1,9 +1,9 @@
package buzzer
const (
Whole = 4
Half = 2
Quarter = 1
Whole = 4.0
Half = 2.0
Quarter = 1.0
Eighth = 0.500
)
+2 -27
View File
@@ -1,3 +1,5 @@
//go:build tinygo
// 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
@@ -7,34 +9,10 @@
package dht // import "tinygo.org/x/drivers/dht"
import (
"encoding/binary"
"machine"
"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
type TemperatureScale uint8
@@ -54,9 +32,6 @@ const (
startTimeout = time.Millisecond * 200
startingLow = time.Millisecond * 20
DHT11 DeviceType = iota
DHT22
C TemperatureScale = iota
F
+44
View File
@@ -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
}
+46
View File
@@ -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
View File
@@ -1,5 +1,4 @@
//go:build mimxrt1062 || stm32f405 || atsamd51 || stm32f103xx || k210 || stm32f407
// +build mimxrt1062 stm32f405 atsamd51 stm32f103xx k210 stm32f407
package dht // import "tinygo.org/x/drivers/dht"
-1
View File
@@ -1,5 +1,4 @@
//go:build !mimxrt1062 && !stm32f405 && !atsamd51 && !stm32f103xx && !k210 && !stm32f407
// +build !mimxrt1062,!stm32f405,!atsamd51,!stm32f103xx,!k210,!stm32f407
package dht // import "tinygo.org/x/drivers/dht"
+5 -2
View File
@@ -1,3 +1,5 @@
//go:build tinygo
// 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
@@ -8,6 +10,7 @@ package dht // import "tinygo.org/x/drivers/dht"
import (
"machine"
"runtime/interrupt"
"time"
)
@@ -157,8 +160,8 @@ func (t *device) read() error {
// interrupts
func receiveSignals(pin machine.Pin, result []counter) {
i := uint8(0)
machine.UART1.Interrupt.Disable()
defer machine.UART1.Interrupt.Enable()
mask := interrupt.Disable()
defer interrupt.Restore(mask)
for ; i < 40; i++ {
result[i*2] = expectChange(pin, false)
result[i*2+1] = expectChange(pin, true)
+2
View File
@@ -1,3 +1,5 @@
//go:build tinygo
// 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
+2
View File
@@ -1,3 +1,5 @@
//go:build tinygo
package dht // import "tinygo.org/x/drivers/dht"
import (
+7 -8
View File
@@ -3,22 +3,22 @@
//
// Here is an example in TinyGo that uses the BMP180 digital barometer:
//
// package main
// package main
//
// import (
// import (
// "time"
// "machine"
//
// "tinygo.org/x/drivers/bmp180"
// )
// "tinygo.org/x/drivers/bmp180"
// )
//
// func main() {
// func main() {
// machine.I2C0.Configure(machine.I2CConfig{})
// sensor := bmp180.New(machine.I2C0)
// sensor.Configure()
//
// connected := sensor.Connected()
// if !connected {
// connected := sensor.Connected()
// if !connected {
// println("BMP180 not detected")
// return
// }
@@ -38,5 +38,4 @@
// Each individual driver is contained within its own sub-package within this package and
// there are no interdependencies in order to minimize the final size of compiled code that
// uses any of these drivers.
//
package drivers // import "tinygo.org/x/drivers"
-1
View File
@@ -2,7 +2,6 @@
//
// Datasheet:
// https://datasheets.maximintegrated.com/en/ds/DS1307.pdf
//
package ds1307 // import "tinygo.org/x/drivers/ds1307"
import (
+138 -22
View File
@@ -2,28 +2,76 @@
package easystepper // import "tinygo.org/x/drivers/easystepper"
import (
"errors"
"machine"
"time"
)
// StepMode determines the coil sequence used to perform a single step
type StepMode uint8
// Valid values for StepMode
const (
// ModeFour uses a 'four step' coil sequence (12-23-34-41). This is the default (zero-value) mode
ModeFour StepMode = iota
// ModeEight uses an 'eight step' coil sequence (1-12-2-23-3-34-4-41)
ModeEight
)
// stepCount is a helper function to return the number of steps in a StepMode sequence
func (sm StepMode) stepCount() uint {
switch sm {
default:
fallthrough
case ModeFour:
return 4
case ModeEight:
return 8
}
}
// DeviceConfig contains the configuration data for a single easystepper driver
type DeviceConfig struct {
// Pin1 ... Pin4 determines the pins to configure and use for the device
Pin1, Pin2, Pin3, Pin4 machine.Pin
// StepCount is the number of steps required to perform a full revolution of the stepper motor
StepCount uint
// RPM determines the speed of the stepper motor in 'Revolutions per Minute'
RPM uint
// Mode determines the coil sequence used to perform a single step
Mode StepMode
}
// DualDeviceConfig contains the configuration data for a dual easystepper driver
type DualDeviceConfig struct {
DeviceConfig
// Pin5 ... Pin8 determines the pins to configure and use for the second device
Pin5, Pin6, Pin7, Pin8 machine.Pin
}
// Device holds the pins and the delay between steps
type Device struct {
pins [4]machine.Pin
stepDelay int32
stepDelay time.Duration
stepNumber uint8
stepMode StepMode
}
// DualDevice holds information for controlling 2 motors
type DualDevice struct {
devices [2]Device
devices [2]*Device
}
// New returns a new easystepper driver given 4 pins, number of steps and rpm
func New(pin1, pin2, pin3, pin4 machine.Pin, steps int32, rpm int32) Device {
return Device{
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
stepDelay: 60000000 / (steps * rpm),
// New returns a new single easystepper driver given a DeviceConfig
func New(config DeviceConfig) (*Device, error) {
if config.StepCount == 0 || config.RPM == 0 {
return nil, errors.New("config.StepCount and config.RPM must be > 0")
}
return &Device{
pins: [4]machine.Pin{config.Pin1, config.Pin2, config.Pin3, config.Pin4},
stepDelay: time.Second * 60 / time.Duration((config.StepCount * config.RPM)),
stepMode: config.Mode,
}, nil
}
// Configure configures the pins of the Device
@@ -34,17 +82,23 @@ func (d *Device) Configure() {
}
// NewDual returns a new dual easystepper driver given 8 pins, number of steps and rpm
func NewDual(pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8 machine.Pin, steps int32, rpm int32) DualDevice {
var dual DualDevice
dual.devices[0] = Device{
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
stepDelay: 60000000 / (steps * rpm),
func NewDual(config DualDeviceConfig) (*DualDevice, error) {
// Create the first device
dev1, err := New(config.DeviceConfig)
if err != nil {
return nil, err
}
dual.devices[1] = Device{
pins: [4]machine.Pin{pin5, pin6, pin7, pin8},
stepDelay: 60000000 / (steps * rpm),
// Create the second device
config.DeviceConfig.Pin1 = config.Pin5
config.DeviceConfig.Pin2 = config.Pin6
config.DeviceConfig.Pin3 = config.Pin7
config.DeviceConfig.Pin4 = config.Pin8
dev2, err := New(config.DeviceConfig)
if err != nil {
return nil, err
}
return dual
// Return composite dual device
return &DualDevice{devices: [2]*Device{dev1, dev2}}, nil
}
// Configure configures the pins of the DualDevice
@@ -64,7 +118,7 @@ func (d *Device) Move(steps int32) {
var s int32
d.stepMotor(d.stepNumber)
for s = int32(d.stepNumber); s < steps; s++ {
time.Sleep(time.Duration(d.stepDelay) * time.Microsecond)
time.Sleep(d.stepDelay)
d.moveDirectionSteps(direction, s)
}
}
@@ -101,7 +155,7 @@ func (d *DualDevice) Move(stepsA, stepsB int32) {
stepsA += int32(d.devices[max].stepNumber)
minStep = int32(d.devices[min].stepNumber)
for s := int32(d.devices[max].stepNumber); s < stepsA; s++ {
time.Sleep(time.Duration(d.devices[0].stepDelay) * time.Microsecond)
time.Sleep(d.devices[0].stepDelay)
d.devices[max].moveDirectionSteps(directions[max], s)
if ((s * stepsB) / stepsA) > minStep {
@@ -119,6 +173,18 @@ func (d *DualDevice) Off() {
// stepMotor changes the pins' state to the correct step
func (d *Device) stepMotor(step uint8) {
switch d.stepMode {
default:
fallthrough
case ModeFour:
d.stepMotor4(step)
case ModeEight:
d.stepMotor8(step)
}
}
// stepMotor4 changes the pins' state to the correct step in 4-step mode
func (d *Device) stepMotor4(step uint8) {
switch step {
case 0:
d.pins[0].High()
@@ -148,13 +214,63 @@ func (d *Device) stepMotor(step uint8) {
d.stepNumber = step
}
// stepMotor8 changes the pins' state to the correct step in 8-step mode
func (d *Device) stepMotor8(step uint8) {
switch step {
case 0:
d.pins[0].High()
d.pins[2].Low()
d.pins[1].Low()
d.pins[3].Low()
case 1:
d.pins[0].High()
d.pins[2].High()
d.pins[1].Low()
d.pins[3].Low()
case 2:
d.pins[0].Low()
d.pins[2].High()
d.pins[1].Low()
d.pins[3].Low()
case 3:
d.pins[0].Low()
d.pins[2].High()
d.pins[1].High()
d.pins[3].Low()
case 4:
d.pins[0].Low()
d.pins[2].Low()
d.pins[1].High()
d.pins[3].Low()
case 5:
d.pins[0].Low()
d.pins[2].Low()
d.pins[1].High()
d.pins[3].High()
case 6:
d.pins[0].Low()
d.pins[2].Low()
d.pins[1].Low()
d.pins[3].High()
case 7:
d.pins[0].High()
d.pins[2].Low()
d.pins[1].Low()
d.pins[3].High()
}
d.stepNumber = step
}
// moveDirectionSteps uses the direction to calculate the correct step and change the motor to it.
// Direction true: 0, 1, 2, 3, 0, 1, 2, ...
// Direction false: 0, 3, 2, 1, 0, 3, 2, ...
// Direction true: (4-step mode) 0, 1, 2, 3, 0, 1, 2, ...
// Direction false: (4-step mode) 0, 3, 2, 1, 0, 3, 2, ...
// Direction true: (8-step mode) 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, ...
// Direction false: (8-step mode) 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, ...
func (d *Device) moveDirectionSteps(direction bool, step int32) {
modulus := int32(d.stepMode.stepCount())
if direction {
d.stepMotor(uint8(step % 4))
d.stepMotor(uint8(step % modulus))
} else {
d.stepMotor(uint8((step + 2*(step%2)) % 4))
d.stepMotor(uint8(((-step % modulus) + modulus) % modulus))
}
}
+20
View File
@@ -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()
}
-1
View File
@@ -15,7 +15,6 @@
//
// AT command set:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
package espat // import "tinygo.org/x/drivers/espat"
import (
+1 -1
View File
@@ -29,7 +29,7 @@ func (d *Device) GetDNS(domain string) (string, error) {
return "", errors.New("Invalid domain lookup result")
}
res := strings.Split(r[1], "\r\n")
return res[0], nil
return strings.Trim(res[0], `"`), nil
}
// ConnectTCPSocket creates a new TCP socket connection for the ESP8266/ESP32.
+39
View File
@@ -0,0 +1,39 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/apds9960"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
sensor.Configure(apds9960.Configuration{}) // use default settings
if !sensor.Connected() {
println("APDS-9960 not connected!")
return
}
sensor.EnableColor() // enable color engine
for {
if sensor.ColorAvailable() {
r, g, b, c := sensor.ReadColor()
println("Red =", r, "\tGreen =", g, "\tBlue =", b, "\tClear =", c)
}
time.Sleep(time.Millisecond * 100)
}
}
+52
View File
@@ -0,0 +1,52 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/apds9960"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
sensor.Configure(apds9960.Configuration{}) // use default settings
if !sensor.Connected() {
println("APDS-9960 not connected!")
return
}
sensor.EnableGesture() // enable gesture engine
for {
// wave your hand (not too slow) about 10 cm above the sensor
if sensor.GestureAvailable() {
gesture := sensor.ReadGesture()
print("Detected gesture: ")
switch gesture {
case apds9960.GESTURE_UP: // the nRF52 chip is "up"
println("Up")
case apds9960.GESTURE_DOWN:
println("Down")
case apds9960.GESTURE_LEFT:
println("Left")
case apds9960.GESTURE_RIGHT:
println("Right")
}
}
// note: the delay shouldn't be too long, otherwise new gesture data might be lost
time.Sleep(time.Millisecond * 250)
}
}
+40
View File
@@ -0,0 +1,40 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/apds9960"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
// use default settings
sensor.Configure(apds9960.Configuration{})
if !sensor.Connected() {
println("APDS-9960 not connected!")
return
}
sensor.EnableProximity() // enable proximity engine
for {
if sensor.ProximityAvailable() {
p := sensor.ReadProximity()
println("Proximity:", p)
}
time.Sleep(time.Millisecond * 100)
}
}
@@ -0,0 +1,25 @@
package main
import (
"machine"
"time"
axp192 "tinygo.org/x/drivers/axp192/m5stack-core2-axp192"
"tinygo.org/x/drivers/i2csoft"
)
func main() {
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
axp := axp192.New(i2c)
led := axp.LED
for {
led.Low()
time.Sleep(time.Millisecond * 500)
led.High()
time.Sleep(time.Millisecond * 500)
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ func main() {
dhtSensor := dht.New(pin, dht.DHT11)
for {
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)
} else {
fmt.Printf("Could not take measurements from the sensor: %s\n", err.Error())
+5 -1
View File
@@ -8,7 +8,11 @@ import (
)
func main() {
motor := easystepper.New(machine.P13, machine.P15, machine.P14, machine.P16, 200, 75)
config := easystepper.DeviceConfig{
Pin1: machine.P13, Pin2: machine.P15, Pin3: machine.P14, Pin4: machine.P16,
StepCount: 200, RPM: 75, Mode: easystepper.ModeFour,
}
motor, _ := easystepper.New(config)
motor.Configure()
for {
+8 -6
View File
@@ -6,7 +6,6 @@
//
// More information on the Espressif AT command set at:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
package main
import (
@@ -19,9 +18,11 @@ import (
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
var (
// access point info
ssid string
pass string
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
@@ -113,8 +114,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+8 -6
View File
@@ -3,7 +3,6 @@
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
//
package main
import (
@@ -17,9 +16,11 @@ import (
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
var (
// access point info
ssid string
pass string
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
@@ -99,8 +100,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+8 -6
View File
@@ -3,7 +3,6 @@
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
//
package main
import (
@@ -14,9 +13,11 @@ import (
"tinygo.org/x/drivers/net"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
var (
// access point info
ssid string
pass string
)
// IP address of the listener aka "hub". Replace with your own info.
const hubIP = "0.0.0.0"
@@ -88,8 +89,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+9 -7
View File
@@ -7,8 +7,7 @@
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
// go get -u github.com/eclipse/paho.mqtt.golang
package main
import (
@@ -20,9 +19,11 @@ import (
"tinygo.org/x/drivers/net/mqtt"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
var (
// access point info
ssid string
pass string
)
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
@@ -108,8 +109,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+9 -7
View File
@@ -7,8 +7,7 @@
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
// go get -u github.com/eclipse/paho.mqtt.golang
package main
import (
@@ -21,9 +20,11 @@ import (
"tinygo.org/x/drivers/net/mqtt"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
var (
// access point info
ssid string
pass string
)
// IP address of the MQTT broker to use. Replace with your own info.
//const server = "tcp://test.mosquitto.org:1883"
@@ -129,8 +130,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+8 -6
View File
@@ -3,7 +3,6 @@
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
//
package main
import (
@@ -14,9 +13,11 @@ import (
"tinygo.org/x/drivers/net"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
const serverIP = "0.0.0.0"
@@ -91,8 +92,9 @@ func connectToESP() bool {
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
+23
View File
@@ -0,0 +1,23 @@
//go:build m5stack_core2
package main
import (
"machine"
"tinygo.org/x/drivers/ft6336"
"tinygo.org/x/drivers/i2csoft"
"tinygo.org/x/drivers/touch"
)
// InitDisplay initializes the display of each board.
func initDevices() (touch.Pointer, error) {
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
resistiveTouch := ft6336.New(i2c, machine.Pin(39))
resistiveTouch.Configure(ft6336.Config{})
resistiveTouch.SetPeriodActive(0x00)
return resistiveTouch, nil
}
+16
View File
@@ -0,0 +1,16 @@
package main
func main() {
touchScreen, _ := initDevices()
for {
touch := touchScreen.ReadTouchPoint()
if touch.Z > 0 {
//X and Y are 16 bit with 12 bit resolution and need to be scaled for the display size
//Z is 24 bit and is typically > 2000 for a touch
println("touch:", touch.X, touch.Y, touch.Z)
//Example of scaling for m5stack-core2's 320x240 display with 320x270 touch area
println("screen:", (touch.X*320)>>16, (touch.Y*270)>>16)
}
}
}
@@ -0,0 +1,54 @@
//go:build m5stack_core2
package main
import (
"image/color"
"machine"
axp192 "tinygo.org/x/drivers/axp192/m5stack-core2-axp192"
"tinygo.org/x/drivers/ft6336"
"tinygo.org/x/drivers/i2csoft"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/touch"
)
// InitDisplay initializes the display of each board.
func initDevices() (touchPaintDisplay, touch.Pointer, error) {
machine.SPI2.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40e6,
})
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
axp := axp192.New(i2c)
led := axp.LED
led.Low()
display := ili9341.NewSPI(
machine.SPI2,
machine.LCD_DC_PIN,
machine.LCD_SS_PIN,
machine.NoPin,
)
// configure display
display.Configure(ili9341.Config{
Width: 320,
Height: 240,
DisplayInversion: true,
})
display.FillScreen(color.RGBA{255, 255, 255, 255})
display.SetRotation(ili9341.Rotation0Mirror)
resistiveTouch := ft6336.New(i2c, machine.Pin(39))
resistiveTouch.Configure(ft6336.Config{})
resistiveTouch.SetPeriodActive(0x00)
return display, resistiveTouch, nil
}
+163
View File
@@ -0,0 +1,163 @@
package main
import (
"image/color"
"math"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/touch"
)
type touchPaintDisplay interface {
drivers.Displayer
FillRectangle(x, y, width, height int16, c color.RGBA) error
DrawRectangle(x, y, w, h int16, c color.RGBA) error
}
var (
white = color.RGBA{255, 255, 255, 255}
black = color.RGBA{0, 0, 0, 255}
red = color.RGBA{255, 0, 0, 255}
green = color.RGBA{0, 255, 0, 255}
blue = color.RGBA{0, 0, 255, 255}
magenta = color.RGBA{255, 0, 255, 255}
yellow = color.RGBA{255, 255, 0, 255}
cyan = color.RGBA{0, 255, 255, 255}
oldColor color.RGBA
currentColor color.RGBA
)
const (
penRadius = 3
boxSize = 30
Xmin = 0
Xmax = 0xFFFF
Ymin = 0
Ymax = 0xFFFF
)
func main() {
display, resistiveTouch, _ := initDevices()
// fill the background and activate the backlight
width, height := display.Size()
display.FillRectangle(0, 0, width, height, black)
// make color selection boxes
display.FillRectangle(0, 0, boxSize, boxSize, red)
display.FillRectangle(boxSize, 0, boxSize, boxSize, yellow)
display.FillRectangle(boxSize*2, 0, boxSize, boxSize, green)
display.FillRectangle(boxSize*3, 0, boxSize, boxSize, cyan)
display.FillRectangle(boxSize*4, 0, boxSize, boxSize, blue)
display.FillRectangle(boxSize*5, 0, boxSize, boxSize, magenta)
display.FillRectangle(boxSize*6, 0, boxSize, boxSize, black)
display.FillRectangle(boxSize*7, 0, boxSize, boxSize, white)
// set the initial color to red and draw a box to highlight it
oldColor = red
currentColor = red
display.DrawRectangle(0, 0, boxSize, boxSize, white)
last := touch.Point{}
// loop and poll for touches, including performing debouncing
debounce := 0
for {
point := resistiveTouch.ReadTouchPoint()
touch := touch.Point{}
if point.Z>>6 > 100 {
rawX := mapval(point.X, Xmin, Xmax, 0, int(width))
rawY := mapval(point.Y, Ymin, Ymax, 0, int(height))
touch.X = rawX
touch.Y = rawY
touch.Z = 1
} else {
touch.X = 0
touch.Y = 0
touch.Z = 0
}
if last.Z != touch.Z {
debounce = 0
last = touch
} else if math.Abs(float64(touch.X-last.X)) > 4 ||
math.Abs(float64(touch.Y-last.Y)) > 4 {
debounce = 0
last = touch
} else if debounce > 1 {
debounce = 0
HandleTouch(display, last)
} else if touch.Z > 0 {
debounce++
} else {
last = touch
debounce = 0
}
}
}
// based on Arduino's "map" function
func mapval(x int, inMin int, inMax int, outMin int, outMax int) int {
return (x-inMin)*(outMax-outMin)/(inMax-inMin) + outMin
}
func HandleTouch(display touchPaintDisplay, touch touch.Point) {
if int16(touch.Y) < boxSize {
oldColor = currentColor
x := int16(touch.X)
switch {
case x < boxSize:
currentColor = red
case x < boxSize*2:
currentColor = yellow
case x < boxSize*3:
currentColor = green
case x < boxSize*4:
currentColor = cyan
case x < boxSize*5:
currentColor = blue
case x < boxSize*6:
currentColor = magenta
case x < boxSize*7:
currentColor = black
case x < boxSize*8:
currentColor = white
}
if oldColor == currentColor {
return
}
display.DrawRectangle((x/boxSize)*boxSize, 0, boxSize, boxSize, white)
switch oldColor {
case red:
x = 0
case yellow:
x = boxSize
case green:
x = boxSize * 2
case cyan:
x = boxSize * 3
case blue:
x = boxSize * 4
case magenta:
x = boxSize * 5
case black:
x = boxSize * 6
case white:
x = boxSize * 7
}
display.FillRectangle(int16(x), 0, boxSize, boxSize, oldColor)
}
if (int16(touch.Y) - penRadius) > boxSize {
display.FillRectangle(
int16(touch.X), int16(touch.Y), penRadius*2, penRadius*2, currentColor)
}
}
+39
View File
@@ -0,0 +1,39 @@
package main
import (
"machine"
"time"
"image/color"
"tinygo.org/x/drivers/gc9a01"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 80000000,
})
display := gc9a01.New(machine.SPI0, machine.P6, machine.P7, machine.P8, machine.P9)
display.Configure(gc9a01.Config{Orientation: gc9a01.HORIZONTAL, Width: 240, Height: 240})
width, height := display.Size()
white := color.RGBA{255, 255, 255, 255}
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
green := color.RGBA{0, 255, 0, 255}
black := color.RGBA{0, 0, 0, 255}
display.FillScreen(black)
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
for {
time.Sleep(time.Hour)
}
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/hts221"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := hts221.New(machine.I2C1)
sensor.Configure() // power on and calibrate
if !sensor.Connected() {
println("HTS221 not connected!")
return
}
for {
h, _ := sensor.ReadHumidity()
t, _ := sensor.ReadTemperature()
println("h =", float32(h)/100.0, "% / t =", float32(t)/1000.0, "*C")
time.Sleep(time.Second)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/adt7410"
"tinygo.org/x/drivers/i2csoft"
)
func main() {
i2c := i2csoft.New(machine.SCL_PIN, machine.SDA_PIN)
i2c.Configure(i2csoft.I2CConfig{
Frequency: 400e3,
})
sensor := adt7410.New(i2c)
sensor.Configure()
for {
temp := sensor.ReadTempF()
fmt.Printf("temperature: %f\r\n", temp)
time.Sleep(time.Second)
}
}
-30
View File
@@ -1,30 +0,0 @@
//go:build atsamd21
// +build atsamd21
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
backlight = machine.D3
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
}
+6 -7
View File
@@ -2,9 +2,9 @@ package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/ili9341"
)
@@ -16,16 +16,15 @@ var (
green = color.RGBA{0, 255, 0, 255}
)
var (
display *ili9341.Device
)
func main() {
display = initdisplay.InitDisplay()
backlight.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
width, height := display.Size()
display.FillScreen(black)
backlight.High()
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
-23
View File
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
-30
View File
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
)
func init() {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
}
+38
View File
@@ -0,0 +1,38 @@
//go:build atsamd21
package initdisplay
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
func InitDisplay() *ili9341.Device {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
// configure backlight
backlight := machine.D3
backlight.Configure(machine.PinConfig{machine.PinOutput})
display := ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
// configure display
display.Configure(ili9341.Config{})
backlight.High()
display.SetRotation(ili9341.Rotation270)
return display
}
+41
View File
@@ -0,0 +1,41 @@
//go: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
}
+42
View File
@@ -0,0 +1,42 @@
//go: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,48 @@
//go: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
}
+33
View File
@@ -0,0 +1,33 @@
//go:build pyportal
package initdisplay
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
func InitDisplay() *ili9341.Device {
display := ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
// configure backlight
backlight := machine.TFT_BACKLIGHT
backlight.Configure(machine.PinConfig{machine.PinOutput})
// configure display
display.Configure(ili9341.Config{})
backlight.High()
display.SetRotation(ili9341.Rotation270)
return display
}
@@ -0,0 +1,38 @@
//go:build wioterminal
package initdisplay
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
func InitDisplay() *ili9341.Device {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
// configure backlight
backlight := machine.LCD_BACKLIGHT
backlight.Configure(machine.PinConfig{machine.PinOutput})
display := ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
// configure display
display.Configure(ili9341.Config{})
backlight.High()
display.SetRotation(ili9341.Rotation270)
return display
}
+6 -9
View File
@@ -3,9 +3,9 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/examples/ili9341/pyportal_boing/graphics"
"tinygo.org/x/drivers/ili9341"
)
@@ -44,20 +44,17 @@ var (
palette [16]uint16
)
var (
display *ili9341.Device
)
func main() {
display = initdisplay.InitDisplay()
// configure backlight
backlight.Configure(machine.PinConfig{machine.PinOutput})
// configure display
display.Configure(ili9341.Config{})
print("width, height == ")
width, height := display.Size()
println(width, height)
backlight.High()
display.SetRotation(ili9341.Rotation270)
DrawBackground()
startTime = time.Now().UnixNano()
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
)
func init() {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
}
-30
View File
@@ -1,30 +0,0 @@
//go:build atsamd21
// +build atsamd21
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
backlight = machine.D3
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
}
+6 -7
View File
@@ -2,9 +2,9 @@ package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/ili9341"
)
@@ -16,16 +16,15 @@ var (
white = color.RGBA{255, 255, 255, 255}
)
var (
display *ili9341.Device
)
func main() {
display := initdisplay.InitDisplay()
backlight.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
width, height := display.Size()
display.FillScreen(black)
backlight.High()
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
-23
View File
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
-30
View File
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
)
func init() {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
}
-30
View File
@@ -1,30 +0,0 @@
//go:build atsamd21
// +build atsamd21
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI0,
machine.D0,
machine.D1,
machine.D2,
)
backlight = machine.D3
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Frequency: 24000000,
})
}
+10 -7
View File
@@ -3,10 +3,10 @@ package main
import (
"fmt"
"image/color"
"machine"
"strings"
"time"
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/image/jpeg"
"tinygo.org/x/drivers/image/png"
@@ -20,6 +20,10 @@ var (
green = color.RGBA{0, 255, 0, 255}
)
var (
display *ili9341.Device
)
func main() {
err := run()
for err != nil {
@@ -28,9 +32,7 @@ func main() {
}
func run() error {
backlight.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
display = initdisplay.InitDisplay()
width, height := display.Size()
if width < 320 || height < 240 {
@@ -38,7 +40,6 @@ func run() error {
}
display.FillScreen(black)
backlight.High()
for {
err := drawJpeg(display)
@@ -71,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 {
@@ -83,7 +85,8 @@ func drawJpeg(display *ili9341.Device) error {
}
})
return jpeg.Decode(p)
_, err := jpeg.Decode(p)
return err
}
func errorMessage(err error) {
-23
View File
@@ -1,23 +0,0 @@
//go:build pyportal
// +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
backlight = machine.TFT_BACKLIGHT
)
-30
View File
@@ -1,30 +0,0 @@
//go:build wioterminal
// +build wioterminal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
)
func init() {
machine.SPI3.Configure(machine.SPIConfig{
SCK: machine.LCD_SCK_PIN,
SDO: machine.LCD_SDO_PIN,
SDI: machine.LCD_SDI_PIN,
Frequency: 40000000,
})
}
+58
View File
@@ -0,0 +1,58 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/irremote"
)
var irCmdButtons = map[uint16]string{
0x45: "POWER",
0x47: "FUNC/STOP",
0x46: "VOL+",
0x44: "FAST BACK",
0x40: "PAUSE",
0x43: "FAST FORWARD",
0x07: "DOWN",
0x15: "VOL-",
0x09: "UP",
0x19: "EQ",
0x0D: "ST/REPT",
0x16: "0",
0x0C: "1",
0x18: "2",
0x5E: "3",
0x08: "4",
0x1C: "5",
0x5A: "6",
0x42: "7",
0x52: "8",
0x4A: "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)
}
}
+51
View File
@@ -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)
}
}
+39
View File
@@ -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)
}
}
+41
View File
@@ -0,0 +1,41 @@
# AT-CMD implementation of at-lora command set
This example implements the AT command set as used by Seeed in the LoRa-E5 series of boards, but in the form of a TinyGo program that provides a serial interface.
See https://files.seeedstudio.com/products/317990687/res/LoRa-E5%20AT%20Command%20Specification_V1.0%20.pdf for more information.
```
$ tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
+AT: OK
+VER: 0.0.1 (sx127x v18)
```
# Building
Run the following commands from the main `drivers` directory.
## Simulator
Builds/flashes atcmd console application with simulator instead of actual LoRa radio.
```
tinygo flash -target pico ./examples/lora/lorawan/atcmd/
```
## PyBadge with LoRa Featherwing
Builds/flashes atcmd console application on PyBadge using LoRa Featherwing (RFM95/SX1276).
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/atcmd/
```
## LoRa-E5
Builds/flashes atcmd console application on Lora-E5 using onboard SX126x.
```
tinygo flash -target lorae5 ./examples/lora/lorawan/atcmd/
```
+485
View File
@@ -0,0 +1,485 @@
package main
import (
"encoding/hex"
"strings"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora/lorawan"
)
// Use to test if connection to module is OK.
func quicktest() {
writeCommandOutput("AT", "OK")
}
// Check firmware version.
func version() {
writeCommandOutput("VER", common.CurrentVersion()+" ("+common.FirmwareVersion()+")")
}
// Use to check the ID of the LoRaWAN module, or change the ID.
func id(args string) error {
cmd := "ID"
// look for comma in args
param, val, hasComma := strings.Cut(args, ",")
if hasComma {
// set
data := strings.Trim(val, "\"'")
// convert data from hex formatted string
data = strings.ReplaceAll(data, " ", "")
hexdata, err := hex.DecodeString(data)
if err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
switch param {
case "DevAddr":
if err := session.SetDevAddr(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
case "DevEui":
if err := otaa.SetDevEUI(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
case "AppEui":
if err := otaa.SetAppEUI(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
default:
return errInvalidCommand
}
return nil
}
// get
switch param {
case "DevAddr":
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
case "DevEui":
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
case "AppEui":
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
default:
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
}
return nil
}
// Use to reset the module. If module returns error, then reset function is invalid.
func reset() error {
radio.Reset()
writeCommandOutput("RESET", "OK")
return nil
}
// Use to send string format frame which is no need to be confirmed by the server.
func msg(data string) error {
cmd := "MSG"
writeCommandOutput(cmd, "Start")
if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send string format frame which must be confirmed by the server
func cmsg(data string) error {
cmd := "CMSG"
writeCommandOutput(cmd, "Start")
if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
// TODO: confirmation
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send hex format frame which is no need to be confirmed by the server
func msghex(data string) error {
cmd := "MSGHEX"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send hex format frame which must be confirmed by the server.
func cmsghex(data string) error {
cmd := "CMSGHEX"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send string format LoRaWAN proprietary frames
func pmsg(data string) error {
cmd := "PMSG"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Use to send hex format LoRaWAN proprietary frames.
func pmsghex(data string) error {
cmd := "PMSGHEX"
writeCommandOutput(cmd, "Start")
writeCommandOutput(cmd, "Done")
return nil
}
// Set PORT number which will be used by MSG/CMSG/MSGHEX/CMSGHEX command to send
// message, port number should range from 1 to 255. User should refer to LoRaWAN
// specification to choose port.
func port(p string) error {
cmd := "PMSG"
writeCommandOutput(cmd, p)
return nil
}
// Set ADR function of LoRaWAN module
func adr(state string) error {
cmd := "ADR"
writeCommandOutput(cmd, state)
return nil
}
// Use LoRaWAN defined DRx to set datarate of LoRaWAN AT modem.
func dr(rate string) error {
cmd := "DR"
writeCommandOutput(cmd, rate)
return nil
}
// Channel Configuration
func ch(channel string) error {
cmd := "CH"
writeCommandOutput(cmd, channel)
return nil
}
// Set and Check Power
func power(setting string) error {
cmd := "POWER"
writeCommandOutput(cmd, setting)
return nil
}
// Unconfirmed message repeats times.
func rept(setting string) error {
cmd := "REPT"
writeCommandOutput(cmd, setting)
return nil
}
// Confirmed message retry times. Valid range 0~254,
// if retry times is less than 2, only one message will
// be sent. Random delay 3 - 10s between each retry
// (band duty cycle limitation has the priority)
func retry(setting string) error {
cmd := "RETRY"
writeCommandOutput(cmd, setting)
return nil
}
func rxwin2(setting string) error {
cmd := "RXWIN2"
writeCommandOutput(cmd, setting)
return nil
}
func rxwin1(setting string) error {
cmd := "RXWIN1"
writeCommandOutput(cmd, setting)
return nil
}
func key(setting string) error {
cmd := "KEY"
// look for comma in args
param, val, hasComma := strings.Cut(setting, ",")
if hasComma {
// set
data := strings.Trim(val, "\"'")
// convert data from hex formatted string
data = strings.ReplaceAll(data, " ", "")
hexdata, err := hex.DecodeString(data)
if err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
switch param {
case "APPKEY":
if err := otaa.SetAppKey(hexdata); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "APPKEY, "+otaa.GetAppKey())
default:
return errInvalidCommand
}
}
// cannot get keys
return errInvalidCommand
}
func fdefault(setting string) error {
cmd := "FDEFAULT"
writeCommandOutput(cmd, "OK")
return nil
}
func mode(setting string) error {
cmd := "MODE"
writeCommandOutput(cmd, setting)
return nil
}
func join(setting string) error {
// TODO: check that DevEUI, AppEUI, and AppKey have values
cmd := "JOIN"
writeCommandOutput(cmd, "Starting")
if err := lorawan.Join(otaa, session); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Network joined")
writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
writeCommandOutput(cmd, "NetID, "+otaa.GetNetID())
writeCommandOutput(cmd, "NwkSKey, "+session.GetNwkSKey())
writeCommandOutput(cmd, "AppSKey, "+session.GetAppSKey())
writeCommandOutput(cmd, "Done")
return nil
}
func beacon(setting string) error {
cmd := "BEACON"
writeCommandOutput(cmd, "Starting")
writeCommandOutput(cmd, "Done")
return nil
}
func class(setting string) error {
cmd := "CLASS"
writeCommandOutput(cmd, "Starting")
writeCommandOutput(cmd, "Done")
return nil
}
func delay(setting string) error {
cmd := "DELAY"
writeCommandOutput(cmd, setting)
return nil
}
func lw(setting string) error {
cmd := "LW"
writeCommandOutput(cmd, setting)
return nil
}
func wdt(setting string) error {
cmd := "WDT"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func lowpower(setting string) error {
cmd := "LOWPOWER"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func vdd(setting string) error {
cmd := "VDD"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func temp(setting string) error {
cmd := "TEMP"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func rtc(setting string) error {
cmd := "RTC"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func eeprom(setting string) error {
cmd := "EEPROM"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func uartcmd(setting string) error {
cmd := "UART"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func test(setting string) error {
cmd := "TEST"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func log(setting string) error {
cmd := "LOG"
writeCommandOutput(cmd, "Not implemented")
return nil
}
func send(data string) error {
cmd := "SEND"
writeCommandOutput(cmd, "Start")
// remove leading/trailing quotes
data = strings.Trim(data, "\"'")
if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Done")
return nil
}
func sendhex(data string) error {
cmd := "SENDHEX"
writeCommandOutput(cmd, "Start")
// remove leading/trailing quotes
data = strings.Trim(data, "\"'")
// convert data from hex formatted string
data = strings.ReplaceAll(data, " ", "")
payload, err := hex.DecodeString(data)
if err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
if err := radio.Tx(payload, defaultTimeout); err != nil {
writeCommandOutput(cmd, err.Error())
return err
}
writeCommandOutput(cmd, "Done")
return nil
}
func recv(setting string) error {
cmd := "RECV"
data, err := common.Lorarx()
if err != nil {
writeCommandOutput(cmd, "ERROR "+err.Error())
return err
}
writeCommandOutput(cmd, string(data))
return nil
}
func recvhex(setting string) error {
cmd := "RECVHEX"
data, err := common.Lorarx()
if err != nil {
writeCommandOutput(cmd, "ERROR "+err.Error())
return err
}
writeCommandOutput(cmd, string(data))
return nil
}
func crlf() {
uart.Write([]byte("\r\n"))
}
func writeCommandOutput(cmd, data string) {
uart.Write([]byte("+" + cmd + ": "))
uart.Write([]byte(data))
crlf()
}
+76
View File
@@ -0,0 +1,76 @@
// AT command set console running on the device UART to communicate with
// an attached LoRa device.
//
// Computer <-> UART <-> MCU <-> SPI <-> SX126x/SX127x
//
// Connect using default baudrate for this hardware, 8-N-1 with your terminal program.
// For details on the AT command set, see:
// https://files.seeedstudio.com/products/317990687/res/LoRa-E5%20AT%20Command%20Specification_V1.0%20.pdf
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/lora/lorawan"
)
// change these to test a different UART or pins if available
var (
uart = machine.Serial
tx = machine.UART_TX_PIN
rx = machine.UART_RX_PIN
input = make([]byte, 0, 64)
radio lora.Radio
session *lorawan.Session
otaa *lorawan.Otaa
defaultTimeout uint32 = 1000
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
var err error
radio, err = common.SetupLora()
if err != nil {
fail(err.Error())
}
session = &lorawan.Session{}
otaa = &lorawan.Otaa{}
lorawan.UseRadio(radio)
for {
if uart.Buffered() > 0 {
data, _ := uart.ReadByte()
switch data {
case 13:
// return key
if err := parse(input); err != nil {
uart.Write([]byte("ERROR: "))
uart.Write([]byte(err.Error()))
crlf()
}
input = input[:0]
default:
// just capture the character
input = append(input, data)
}
}
time.Sleep(10 * time.Millisecond)
}
}
func fail(msg string) {
for {
uart.Write([]byte(msg))
crlf()
time.Sleep(time.Minute)
}
}
+115
View File
@@ -0,0 +1,115 @@
package main
import (
"errors"
"strings"
)
var (
errInvalidCommand = errors.New("Invalid command")
)
func parse(data []byte) error {
switch {
case len(data) < 2, string(data[0:2]) != "AT":
return errInvalidCommand
case len(data) == 2:
// just the AT command by itself
quicktest()
case len(data) < 6 || data[2] != '+':
return errInvalidCommand
default:
// parse the rest of the command
cmd, args, _ := strings.Cut(string(data[3:]), "=")
return parseCommand(cmd, args)
}
return nil
}
func parseCommand(cmd, args string) error {
switch cmd {
case "VER":
version()
case "ID":
id(args)
case "RESET":
reset()
case "MSG":
msg(args)
case "CMSG":
cmsg(args)
case "MSGHEX":
msghex(args)
case "CMSGHEX":
cmsghex(args)
case "PMSG":
pmsg(args)
case "PMSGHEX":
pmsg(args)
case "PORT":
port(args)
case "ADR":
adr(args)
case "DR":
dr(args)
case "CH":
ch(args)
case "POWER":
power(args)
case "REPT":
rept(args)
case "RETRY":
retry(args)
case "RXWIN2":
rxwin2(args)
case "RXWIN1":
rxwin1(args)
case "KEY":
key(args)
case "FDEFAULT":
fdefault(args)
case "MODE":
mode(args)
case "JOIN":
join(args)
case "BEACON":
join(args)
case "CLASS":
class(args)
case "DELAY":
delay(args)
case "LW":
lw(args)
case "WDT":
wdt(args)
case "LOWPOWER":
lowpower(args)
case "VDD":
vdd(args)
case "TEMP":
temp(args)
case "RTC":
rtc(args)
case "EEPROM":
eeprom(args)
case "UART":
uartcmd(args)
case "TEST":
test(args)
case "LOG":
log(args)
case "RECV":
recv(args)
case "RECVHEX":
recvhex(args)
case "SEND":
send(args)
case "SENDHEX":
sendhex(args)
default:
return errInvalidCommand
}
return nil
}
@@ -0,0 +1,35 @@
# Simple Lorawan example
This demo code will connect Lorawan network and send sample uplink message
You may change your Lorawan keys (AppEUI, DevEUI, AppKEY) in key-default.go
```
$ tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
Lorawan Simple Demo
Start Lorawan Join sequence
loraConnect: Connected !
```
# Building
## Simulator
```
tinygo flash -target pico ./examples/lora/lorawan/basic-demo
```
## PyBadge with LoRa Featherwing
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/basic-demo
```
## LoRa-E5
```
tinygo flash -target lorae5 ./examples/lora/lorawan/basic-demo
```
@@ -0,0 +1,11 @@
//go:build !customkeys
package main
// These are sample keys, so the example builds
// Either change here, or create a new go file and use customkeys build tag
func setLorawanKeys() {
otaa.SetAppEUI([]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
otaa.SetDevEUI([]uint8{0xB3, 0xD5, 0x41, 0x00, 0x0A, 0xF1, 0xA4, 0x45})
otaa.SetAppKey([]uint8{0x12, 0x22, 0xA3, 0xFF, 0x0C, 0x7B, 0x76, 0x7B, 0x8F, 0xD3, 0x12, 0x4F, 0xCE, 0x7A, 0x32, 0x16})
}
+107
View File
@@ -0,0 +1,107 @@
// Simple code for connecting to Lorawan network and uploading sample payload
package main
import (
"errors"
"strconv"
"time"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/lora/lorawan"
)
const (
LORAWAN_JOIN_TIMEOUT_SEC = 180
LORAWAN_RECONNECT_DELAY_SEC = 15
LORAWAN_UPLINK_DELAY_SEC = 60
)
var (
radio lora.Radio
session *lorawan.Session
otaa *lorawan.Otaa
)
func loraConnect() error {
start := time.Now()
var err error
for time.Since(start) < LORAWAN_JOIN_TIMEOUT_SEC*time.Second {
println("Trying to join network")
err = lorawan.Join(otaa, session)
if err == nil {
println("Connected to network !")
return nil
}
println("Join error:", err, "retrying in", LORAWAN_RECONNECT_DELAY_SEC, "sec")
time.Sleep(time.Second * LORAWAN_RECONNECT_DELAY_SEC)
}
err = errors.New("Unable to join Lorawan network")
println(err.Error())
return err
}
func failMessage(err error) {
println("FATAL:", err)
for {
}
}
func main() {
println("*** Lorawan basic join and uplink demo ***")
// Board specific Lorawan initialization
var err error
radio, err = common.SetupLora()
if err != nil {
failMessage(err)
}
// Required for LoraWan operations
session = &lorawan.Session{}
otaa = &lorawan.Otaa{}
// Initial Lora modulation configuration
loraConf := lora.Config{
Freq: 868100000,
Bw: lora.Bandwidth_125_0,
Sf: lora.SpreadingFactor9,
Cr: lora.CodingRate4_7,
HeaderType: lora.HeaderExplicit,
Preamble: 12,
Ldr: lora.LowDataRateOptimizeOff,
Iq: lora.IQStandard,
Crc: lora.CRCOn,
SyncWord: lora.SyncPublic,
LoraTxPowerDBm: 20,
}
radio.LoraConfig(loraConf)
// Connect the lorawan with the Lora Radio device.
lorawan.UseRadio(radio)
// Configure AppEUI, DevEUI, APPKey
setLorawanKeys()
// Try to connect Lorawan network
if err := loraConnect(); err != nil {
failMessage(err)
}
// Try to periodicaly send an uplink sample message
upCount := 1
for {
payload := "Hello TinyGo #" + strconv.Itoa(upCount)
if err := lorawan.SendUplink([]byte(payload), session); err != nil {
println("Uplink error:", err)
} else {
println("Uplink success, msg=", payload)
}
println("Sleeping for", LORAWAN_UPLINK_DELAY_SEC, "sec")
time.Sleep(time.Second * LORAWAN_UPLINK_DELAY_SEC)
upCount++
}
}
+10
View File
@@ -0,0 +1,10 @@
package common
import (
"errors"
)
var (
errRadioNotFound = errors.New("radio not found")
errRxTimeout = errors.New("radio RX timeout")
)
+40
View File
@@ -0,0 +1,40 @@
//go:build !featherwing && !stm32wlx && !sx126x
package common
import "tinygo.org/x/drivers/lora"
// do simulator setup here
func SetupLora() (lora.Radio, error) {
return &SimLoraRadio{}, nil
}
type SimLoraRadio struct {
}
func (sr *SimLoraRadio) Reset() {
}
func (sr *SimLoraRadio) Tx(pkt []uint8, timeoutMs uint32) error {
return nil
}
func (sr *SimLoraRadio) Rx(timeoutMs uint32) ([]uint8, error) {
return nil, nil
}
func (sr *SimLoraRadio) SetFrequency(freq uint32) {}
func (sr *SimLoraRadio) SetIqMode(mode uint8) {}
func (sr *SimLoraRadio) SetCodingRate(cr uint8) {}
func (sr *SimLoraRadio) SetBandwidth(bw uint8) {}
func (sr *SimLoraRadio) SetCrc(enable bool) {}
func (sr *SimLoraRadio) SetSpreadingFactor(sf uint8) {}
func (sr *SimLoraRadio) LoraConfig(cnf lora.Config) {}
func FirmwareVersion() string {
return "simulator " + CurrentVersion()
}
func Lorarx() ([]byte, error) {
return nil, nil
}
+65
View File
@@ -0,0 +1,65 @@
//go:build stm32wlx
package common
import (
"machine"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/sx126x"
)
const (
FREQ = 868100000
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx126x.Device
)
var spi = machine.SPI3
func newRadioControl() sx126x.RadioController {
return sx126x.NewRadioControl()
}
// do sx126x setup here
func SetupLora() (lora.Radio, error) {
loraRadio = sx126x.New(spi)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create radio controller for target
loraRadio.SetRadioController(newRadioControl())
if state := loraRadio.DetectDevice(); !state {
return nil, errRadioNotFound
}
loraConf := lora.Config{
Freq: FREQ,
Bw: lora.Bandwidth_500_0,
Sf: lora.SpreadingFactor9,
Cr: lora.CodingRate4_7,
HeaderType: lora.HeaderExplicit,
Preamble: 12,
Ldr: lora.LowDataRateOptimizeOff,
Iq: lora.IQStandard,
Crc: lora.CRCOn,
SyncWord: lora.SyncPrivate,
LoraTxPowerDBm: 20,
}
loraRadio.LoraConfig(loraConf)
return loraRadio, nil
}
func FirmwareVersion() string {
return "sx126x"
}
func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
}
+69
View File
@@ -0,0 +1,69 @@
//go:build !stm32wlx && sx126x
package common
import (
"machine"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/sx126x"
)
const (
FREQ = 868100000
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx126x.Device
)
var (
spi = machine.SPI0
nssPin, busyPin, dio1Pin = machine.GP17, machine.GP10, machine.GP11
rxPin, txLowPin, txHighPin = machine.GP13, machine.GP12, machine.GP12
)
func newRadioControl() sx126x.RadioController {
return sx126x.NewRadioControl(nssPin, busyPin, dio1Pin, rxPin, txLowPin, txHighPin)
}
// do sx126x setup here
func SetupLora() (lora.Radio, error) {
loraRadio = sx126x.New(spi)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create radio controller for target
loraRadio.SetRadioController(newRadioControl())
if state := loraRadio.DetectDevice(); !state {
return nil, errRadioNotFound
}
loraConf := lora.Config{
Freq: FREQ,
Bw: lora.Bandwidth_500_0,
Sf: lora.SpreadingFactor9,
Cr: lora.CodingRate4_7,
HeaderType: lora.HeaderExplicit,
Preamble: 12,
Ldr: lora.LowDataRateOptimizeOff,
Iq: lora.IQStandard,
Crc: lora.CRCOn,
SyncWord: lora.SyncPrivate,
LoraTxPowerDBm: 20,
}
loraRadio.LoraConfig(loraConf)
return loraRadio, nil
}
func FirmwareVersion() string {
return "sx126x"
}
func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
}
+85
View File
@@ -0,0 +1,85 @@
//go:build featherwing
package common
import (
"strconv"
"machine"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/sx127x"
)
const (
FREQ = 868100000
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
// We assume LoRa Featherwing module is connected to PyBadge:
rstPin = machine.D11
csPin = machine.D10
dio0Pin = machine.D6
dio1Pin = machine.D9
spi = machine.SPI0
loraRadio *sx127x.Device
)
// do sx127x setup here
func SetupLora() (lora.Radio, error) {
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
dio0Pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
dio1Pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
spi.Configure(machine.SPIConfig{Frequency: 500000, Mode: 0})
loraRadio = sx127x.New(spi, csPin, rstPin)
loraRadio.Reset()
if state := loraRadio.DetectDevice(); !state {
return nil, errRadioNotFound
}
// Setup DIO0 interrupt Handling
if err := dio0Pin.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil {
println("could not configure DIO0 pin interrupt:", err.Error())
}
// Setup DIO1 interrupt Handling
if err := dio1Pin.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil {
println("could not configure DIO1 pin interrupt:", err.Error())
}
// Prepare for Lora Operation
loraConf := lora.Config{
Freq: FREQ,
Bw: lora.Bandwidth_125_0,
Sf: lora.SpreadingFactor9,
Cr: lora.CodingRate4_7,
HeaderType: lora.HeaderExplicit,
Preamble: 12,
Iq: lora.IQStandard,
Crc: lora.CRCOn,
SyncWord: lora.SyncPublic,
LoraTxPowerDBm: 20,
}
loraRadio.LoraConfig(loraConf)
return loraRadio, nil
}
func dioIrqHandler(machine.Pin) {
loraRadio.HandleInterrupt()
}
func FirmwareVersion() string {
v := loraRadio.GetVersion()
return "sx127x v" + strconv.Itoa(int(v))
}
func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
}
+7
View File
@@ -0,0 +1,7 @@
package common
const VERSION = "0.0.1"
func CurrentVersion() string {
return VERSION
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lps22hb"
)
func main() {
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := lps22hb.New(machine.I2C1)
sensor.Configure()
if !sensor.Connected() {
println("LPS22HB not connected!")
return
}
for {
p, _ := sensor.ReadPressure()
t, _ := sensor.ReadTemperature()
println("p =", float32(p)/1000.0, "hPa / t =", float32(t)/1000.0, "*C")
time.Sleep(time.Second)
// note: the device would power down itself after each query
}
}
+42 -17
View File
@@ -3,37 +3,62 @@ package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lsm303agr"
)
func main() {
// LSM303AGR/MAG is connected to the I2C0 bus on micro:bit v1 (the same as P19/P20) and v2 (internal)
machine.I2C0.Configure(machine.I2CConfig{})
accel_mag := lsm303agr.New(machine.I2C0)
if !accel_mag.Connected() {
println("LSM303AGR/MAG not connected!")
return
sensor := lsm303agr.New(machine.I2C0)
err := sensor.Configure(lsm303agr.Configuration{}) //default settings
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 {
accel_x, accel_y, accel_z := accel_mag.ReadAcceleration()
pitch, roll := accel_mag.ReadPitchRoll()
mag_x, mag_y, mag_z := accel_mag.ReadMagneticField()
heading := accel_mag.ReadCompass()
temp, _ := accel_mag.ReadTemperature()
if !sensor.Connected() {
println("LSM303AGR/MAG not connected!")
time.Sleep(time.Second)
continue
}
// 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")
time.Sleep(time.Millisecond * 100)
time.Sleep(time.Millisecond * 250)
}
}
+13 -6
View File
@@ -12,16 +12,23 @@ func main() {
machine.I2C0.Configure(machine.I2CConfig{})
accel := lsm6ds3.New(machine.I2C0)
accel.Configure(lsm6ds3.Configuration{})
if !accel.Connected() {
println("LSM6DS3 not connected")
return
err := accel.Configure(lsm6ds3.Configuration{})
if err != nil {
for {
println("Failed to configure", err.Error())
time.Sleep(time.Second)
}
}
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)
x, y, z = accel.ReadRotation()
x, y, z, _ = accel.ReadRotation()
println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
x, _ = accel.ReadTemperature()
println("Degrees C", float32(x)/1000, "\n\n")
+37
View File
@@ -0,0 +1,37 @@
// Connects to an LSM6DS3TR I2C a 6 axis Inertial Measurement Unit (IMU)
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lsm6ds3tr"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
accel := lsm6ds3tr.New(machine.I2C0)
err := accel.Configure(lsm6ds3tr.Configuration{})
if err != nil {
for {
println("Failed to configure", err.Error())
time.Sleep(time.Second)
}
}
for {
if !accel.Connected() {
println("LSM6DS3TR not connected")
time.Sleep(time.Second)
continue
}
x, y, z, _ := accel.ReadAcceleration()
println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
x, y, z, _ = accel.ReadRotation()
println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
x, _ = accel.ReadTemperature()
println("Degrees C", float32(x)/1000, "\n\n")
time.Sleep(time.Millisecond * 1000)
}
}
+10 -4
View File
@@ -26,12 +26,18 @@ func main() {
machine.I2C0.Configure(machine.I2CConfig{})
device := lsm6dsox.New(machine.I2C0)
device.Configure(lsm6dsox.Configuration{
err := device.Configure(lsm6dsox.Configuration{
AccelRange: lsm6dsox.ACCEL_2G,
AccelSampleRate: lsm6dsox.ACCEL_SR_104,
GyroRange: lsm6dsox.GYRO_250DPS,
GyroSampleRate: lsm6dsox.GYRO_SR_104,
})
if err != nil {
for {
println("Failed to configure", err.Error())
time.Sleep(time.Second)
}
}
for {
@@ -46,8 +52,8 @@ func main() {
calibrateGyro(device)
}
ax, ay, az := device.ReadAcceleration()
gx, gy, gz := device.ReadRotation()
ax, ay, az, _ := device.ReadAcceleration()
gx, gy, gz, _ := device.ReadRotation()
t, _ := device.ReadTemperature()
if PLOTTER {
@@ -64,7 +70,7 @@ func main() {
func calibrateGyro(device *lsm6dsox.Device) {
for i := 0; i < 100; i++ {
gx, gy, gz := device.ReadRotation()
gx, gy, gz, _ := device.ReadRotation()
cal[0] += float32(gx) / 1000000
cal[1] += float32(gy) / 1000000
cal[2] += float32(gz) / 1000000
+103
View File
@@ -0,0 +1,103 @@
// LSM9DS1, 9 axis Inertial Measurement Unit (IMU)
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/lsm9ds1"
)
const (
PLOTTER = false
SHOW_ACCELERATION = true
SHOW_ROTATION = true
SHOW_MAGNETIC_FIELD = true
SHOW_TEMPERATURE = true
)
func main() {
// I2C configure
machine.I2C0.Configure(machine.I2CConfig{})
// LSM9DS1 setup
device := lsm9ds1.New(machine.I2C0)
err := device.Configure(lsm9ds1.Configuration{
AccelRange: lsm9ds1.ACCEL_2G,
AccelSampleRate: lsm9ds1.ACCEL_SR_119,
GyroRange: lsm9ds1.GYRO_250DPS,
GyroSampleRate: lsm9ds1.GYRO_SR_119,
MagRange: lsm9ds1.MAG_4G,
MagSampleRate: lsm9ds1.MAG_SR_40,
})
if err != nil {
for {
println("Failed to configure", err.Error())
time.Sleep(time.Second)
}
}
for {
if !device.Connected() {
println("LSM9DS1 not connected")
time.Sleep(time.Second)
continue
}
ax, ay, az, _ := device.ReadAcceleration()
gx, gy, gz, _ := device.ReadRotation()
mx, my, mz, _ := device.ReadMagneticField()
t, _ := device.ReadTemperature()
if PLOTTER {
printPlotter(ax, ay, az, gx, gy, gz, mx, my, mz, t)
time.Sleep(time.Millisecond * 100)
} else {
printMonitor(ax, ay, az, gx, gy, gz, mx, my, mz, t)
time.Sleep(time.Millisecond * 1000)
}
}
}
// Arduino IDE's Serial Plotter
func printPlotter(ax, ay, az, gx, gy, gz, mx, my, mz, t int32) {
if SHOW_ACCELERATION {
fmt.Printf("AX:%f, AY:%f, AZ:%f,", axis(ax), axis(ay), axis(az))
}
if SHOW_ROTATION {
fmt.Printf("GX:%f, GY:%f, GZ:%f,", axis(gx), axis(gy), axis(gz))
}
if SHOW_MAGNETIC_FIELD {
fmt.Printf("MX:%d, MY:%d, MZ:%d,", mx, my, mz)
}
if SHOW_TEMPERATURE {
fmt.Printf("T:%f", float32(t)/1000)
}
println()
}
// Any Serial Monitor
func printMonitor(ax, ay, az, gx, gy, gz, mx, my, mz, t int32) {
if SHOW_ACCELERATION {
fmt.Printf("Acceleration (g): %f, %f, %f\r\n", axis(ax), axis(ay), axis(az))
}
if SHOW_ROTATION {
fmt.Printf("Rotation (dps): %f, %f, %f\r\n", axis(gx), axis(gy), axis(gz))
}
if SHOW_MAGNETIC_FIELD {
fmt.Printf("Magnetic field (nT): %d, %d, %d\r\n", mx, my, mz)
}
if SHOW_TEMPERATURE {
fmt.Printf("Temperature C: %f\r\n", float32(t)/1000)
}
println()
}
func axis(raw int32) float32 {
return float32(raw) / 1000000
}
+31
View File
@@ -0,0 +1,31 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/makeybutton"
)
var (
led machine.Pin = machine.LED
button machine.Pin = machine.D10
key *makeybutton.Button
)
func main() {
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
key = makeybutton.NewButton(button)
key.Configure()
for {
switch key.Get() {
case makeybutton.Pressed:
led.High()
case makeybutton.Released:
led.Low()
}
// the more frequent the more responsive
time.Sleep(50 * time.Millisecond)
}
}
+1
View File
@@ -29,6 +29,7 @@ func main() {
driver.StopDisplayTest()
driver.SetDecodeMode(4)
driver.SetScanLimit(4)
driver.SetIntensity(8)
driver.StopShutdownMode()
for i := 1; i < int(digitNumber); i++ {

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