mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 18:48:41 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6763521eff |
@@ -1,35 +1,3 @@
|
||||
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.
|
||||
|
||||
@@ -17,8 +17,6 @@ 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
|
||||
@@ -65,8 +63,6 @@ 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
|
||||
@@ -83,8 +79,6 @@ 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
|
||||
@@ -211,19 +205,15 @@ 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
|
||||
|
||||
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 i2csoft hts221 lps22hb apds9960 axp192
|
||||
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd
|
||||
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
||||
|
||||
unit-test:
|
||||
@go test -v $(addprefix ./,$(TESTS))
|
||||
@go test -v . $(addprefix ./,$(TESTS))
|
||||
|
||||
test: clean fmt-check unit-test smoke-test
|
||||
|
||||
@@ -52,7 +52,7 @@ func main() {
|
||||
|
||||
## Currently supported devices
|
||||
|
||||
The following 74 devices are supported.
|
||||
The following 67 devices are supported.
|
||||
|
||||
| Device Name | Interface Type |
|
||||
|----------|-------------|
|
||||
@@ -61,9 +61,7 @@ The following 74 devices are supported.
|
||||
| [AHT20 I2C Temperature and Humidity Sensor](http://www.aosong.com/userfiles/files/media/AHT20%20%E8%8B%B1%E6%96%87%E7%89%88%E8%AF%B4%E6%98%8E%E4%B9%A6%20A0%2020201222.pdf) | I2C |
|
||||
| [AMG88xx 8x8 Thermal camera sensor](https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf) | I2C |
|
||||
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
|
||||
| [APDS9960 Digital proximity, ambient light, RGB and gesture sensor](https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf) | I2C |
|
||||
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
|
||||
| [AXP192 single Cell Li-Battery and Power System Management](https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf) | I2C |
|
||||
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
|
||||
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
|
||||
| [BlinkM RGB LED](http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf) | I2C |
|
||||
@@ -81,9 +79,7 @@ The following 74 devices are supported.
|
||||
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
|
||||
| [HC-SR04 Ultrasonic distance sensor](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf) | GPIO |
|
||||
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
|
||||
| [HTS221 digital humidity and temperature sensor](https://www.st.com/resource/en/datasheet/hts221.pdf) | I2C |
|
||||
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
|
||||
| [software I2C driver](https://www.ti.com/lit/an/slva704/slva704.pdf) | GPIO |
|
||||
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
|
||||
| [INA260 Volt/Amp/Power meter](https://www.ti.com/lit/ds/symlink/ina260.pdf) | I2C |
|
||||
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
|
||||
@@ -91,16 +87,12 @@ The following 74 devices are supported.
|
||||
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
||||
| [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C |
|
||||
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
|
||||
| [LPS22HB MEMS nano pressure sensor](https://www.st.com/resource/en/datasheet/dm00140895.pdf) | I2C |
|
||||
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
|
||||
| [LSM6DSOX accelerometer](https://www.st.com/resource/en/datasheet/lsm6dsox.pdf) | I2C |
|
||||
| [LSM303AGR accelerometer](https://www.st.com/resource/en/datasheet/lsm303agr.pdf) | I2C |
|
||||
| [LSM9DS1 accelerometer](https://www.st.com/resource/en/datasheet/lsm9ds1.pdf) | I2C |
|
||||
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
|
||||
| [MAX7219 & MAX7221 display driver](https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf) | SPI |
|
||||
| [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 |
|
||||
| [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 |
|
||||
@@ -113,7 +105,7 @@ The following 74 devices are supported.
|
||||
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
|
||||
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
|
||||
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
|
||||
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
|
||||
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/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 |
|
||||
|
||||
+2
-13
@@ -60,19 +60,8 @@ func (d *Device) Connected() bool {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
return (int32(d.readUint16(RegTempValueMSB)) * 1000) / 128, nil
|
||||
}
|
||||
|
||||
// ReadTempC returns the value in the temperature value register, in Celsius.
|
||||
func (d *Device) ReadTempC() float32 {
|
||||
t := d.readUint16(RegTempValueMSB)
|
||||
return float32(int(t)) / 128.0
|
||||
}
|
||||
|
||||
// ReadTempF returns the value in the temperature value register, in Fahrenheit.
|
||||
func (d *Device) ReadTempF() float32 {
|
||||
return d.ReadTempC()*1.8 + 32.0
|
||||
func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) {
|
||||
return (drivers.Temperature(d.readUint16(RegTempValueMSB)) * 1000) / 128, nil
|
||||
}
|
||||
|
||||
func (d *Device) writeByte(reg uint8, data byte) {
|
||||
|
||||
@@ -1,461 +0,0 @@
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Configure sets up the APDS-9960 device.
|
||||
func (d *Device) Configure(cfg Configuration) {
|
||||
d.DisableAll() // turn off everything
|
||||
|
||||
// "default" settings
|
||||
if cfg.ProximityPulseLength == 0 {
|
||||
cfg.ProximityPulseLength = 16
|
||||
}
|
||||
if cfg.ProximityPulseCount == 0 {
|
||||
cfg.ProximityPulseCount = 64
|
||||
}
|
||||
if cfg.GesturePulseLength == 0 {
|
||||
cfg.GesturePulseLength = 16
|
||||
}
|
||||
if cfg.GesturePulseCount == 0 {
|
||||
cfg.GesturePulseCount = 64
|
||||
}
|
||||
if cfg.ProximityGain == 0 {
|
||||
cfg.ProximityGain = 1
|
||||
}
|
||||
if cfg.GestureGain == 0 {
|
||||
cfg.GestureGain = 1
|
||||
}
|
||||
if cfg.ColorGain == 0 {
|
||||
cfg.ColorGain = 4
|
||||
}
|
||||
if cfg.ADCIntegrationCycles == 0 {
|
||||
cfg.ADCIntegrationCycles = 4
|
||||
}
|
||||
if cfg.threshold == 0 {
|
||||
d.gesture.threshold = 30
|
||||
}
|
||||
if cfg.sensitivity == 0 {
|
||||
d.gesture.sensitivity = 20
|
||||
}
|
||||
|
||||
d.SetProximityPulse(cfg.ProximityPulseLength, cfg.ProximityPulseCount)
|
||||
d.SetGesturePulse(cfg.GesturePulseLength, cfg.GesturePulseCount)
|
||||
d.SetGains(cfg.ProximityGain, cfg.GestureGain, cfg.ColorGain)
|
||||
d.SetADCIntegrationCycles(cfg.ADCIntegrationCycles)
|
||||
|
||||
if cfg.LEDBoost > 0 {
|
||||
d.LEDBoost(cfg.LEDBoost)
|
||||
}
|
||||
}
|
||||
|
||||
// GetMode returns current engine mode
|
||||
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) 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
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
//go:build !nano_33_ble
|
||||
// +build !nano_33_ble
|
||||
|
||||
package apds9960
|
||||
|
||||
import "tinygo.org/x/drivers"
|
||||
|
||||
// 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}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
//go:build nano_33_ble
|
||||
// +build nano_33_ble
|
||||
|
||||
package apds9960
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
// turn on internal power pin (machine.P0_22) and I2C1 pullups power pin (machine.P1_00)
|
||||
// and wait a moment.
|
||||
ENV := machine.P0_22
|
||||
ENV.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
ENV.High()
|
||||
R := machine.P1_00
|
||||
R.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
R.High()
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
|
||||
return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
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
|
||||
)
|
||||
@@ -1,258 +0,0 @@
|
||||
// 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]
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package axp192
|
||||
|
||||
// power supply control class
|
||||
// 0x00 Power supply status register
|
||||
// 0x01 Power supply mode/charging status register
|
||||
// 0x04 OTG VBUS status register
|
||||
// 0x06‐09 Data buffer register
|
||||
// 0x10 EXTEN & DC‐DC2 switch register
|
||||
// 0x12 DC‐DC1/3 & LDO2/3switch register
|
||||
// 0x23 DC‐DC2 voltage set register
|
||||
// 0x25 DC‐DC2 voltage slope set register
|
||||
// 0x26 DC‐DC1voltage set register
|
||||
// 0x27 DC‐DC3 voltage set register
|
||||
// 0x28 LDO2/3 voltage set register
|
||||
// 0x30 VBUS‐IPSOUT 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 bit,monitor battery temperature by default
|
||||
// 0x63 TS input ADC data low 4 bit,monitor 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
|
||||
)
|
||||
+2
-2
@@ -114,14 +114,14 @@ func (d *Device) Reset() {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (int32, error) {
|
||||
func (d *Device) ReadTemperature() (drivers.Temperature, error) {
|
||||
data, err := d.readData()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
temp, _ := d.calculateTemp(data)
|
||||
return temp, nil
|
||||
return drivers.Temperature(temp), nil
|
||||
}
|
||||
|
||||
// ReadPressure returns the pressure in milli pascals mPa
|
||||
|
||||
+2
-2
@@ -81,7 +81,7 @@ func (d *DeviceSPI) Reset() error {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||
func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
|
||||
func (d *DeviceSPI) ReadTemperature() (temperature drivers.Temperature, err error) {
|
||||
data := d.buf[:3]
|
||||
data[0] = 0x80 | reg_TEMPERATURE_0
|
||||
data[1] = 0
|
||||
@@ -109,7 +109,7 @@ func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
|
||||
// rawTemperature * 1000 * 64 / 0x8000 + 23000
|
||||
// rawTemperature * 64000 / 0x8000 + 23000
|
||||
// rawTemperature * 125 / 64 + 23000
|
||||
temperature = int32(rawTemperature)*125/64 + 23000
|
||||
temperature = drivers.Temperature(rawTemperature)*125/64 + 23000
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -81,14 +81,14 @@ func (d *Device) Configure() {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) {
|
||||
rawTemp, err := d.rawTemp()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
b5 := d.calculateB5(rawTemp)
|
||||
t := (b5 + 8) >> 4
|
||||
return 100 * t, nil
|
||||
return drivers.Temperature(100 * t), nil
|
||||
}
|
||||
|
||||
// ReadPressure returns the pressure in milli pascals (mPa).
|
||||
|
||||
+2
-2
@@ -132,7 +132,7 @@ func (d *Device) PrintCali() {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) {
|
||||
data, err := d.readData(REG_TEMP, 3)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -150,7 +150,7 @@ func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
|
||||
// Convert from degrees to milli degrees by multiplying by 10.
|
||||
// Will output 30250 milli degrees celsius for 30.25 degrees celsius
|
||||
temperature = 10 * ((tFine*5 + 128) >> 8)
|
||||
temperature = drivers.Temperature(10 * ((tFine*5 + 128) >> 8))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -133,16 +133,16 @@ func (d *Device) tlinCompensate() (int64, error) {
|
||||
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in centicelsius, i.e 2426 / 100 = 24.26 C
|
||||
func (d *Device) ReadTemperature() (int32, error) {
|
||||
// ReadTemperature returns the temperature in milli degrees Celsius, i.e 24260 / 1000 = 24.26°C.
|
||||
func (d *Device) ReadTemperature() (drivers.Temperature, error) {
|
||||
|
||||
tlin, err := d.tlinCompensate()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
temp := (tlin * 25) / 16384
|
||||
return int32(temp), nil
|
||||
temp := (tlin * 125) / 8192
|
||||
return drivers.Temperature(temp), nil
|
||||
}
|
||||
|
||||
// ReadPressure returns the pressure in centipascals, i.e 10132520 / 100 = 101325.20 Pa
|
||||
|
||||
@@ -35,18 +35,6 @@ func (d DeviceType) extractData(buf []byte) (temp int16, hum uint16) {
|
||||
return
|
||||
}
|
||||
|
||||
// Celsius and Fahrenheit temperature scales
|
||||
type TemperatureScale uint8
|
||||
|
||||
func (t TemperatureScale) convertToFloat(temp int16) float32 {
|
||||
if t == C {
|
||||
return float32(temp) / 10
|
||||
} else {
|
||||
// Fahrenheit
|
||||
return float32(temp)*(9.0/50.) + 32.
|
||||
}
|
||||
}
|
||||
|
||||
// All functions return ErrorCode instance as error. This class can be used for more efficient error processing
|
||||
type ErrorCode uint8
|
||||
|
||||
@@ -57,9 +45,6 @@ const (
|
||||
DHT11 DeviceType = iota
|
||||
DHT22
|
||||
|
||||
C TemperatureScale = iota
|
||||
F
|
||||
|
||||
ChecksumError ErrorCode = iota
|
||||
NoSignalError
|
||||
NoDataError
|
||||
|
||||
+6
-15
@@ -9,14 +9,15 @@ package dht // import "tinygo.org/x/drivers/dht"
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// DummyDevice provides a basic interface for DHT devices.
|
||||
type DummyDevice interface {
|
||||
ReadMeasurements() error
|
||||
Measurements() (temperature int16, humidity uint16, err error)
|
||||
Temperature() (int16, error)
|
||||
TemperatureFloat(scale TemperatureScale) (float32, error)
|
||||
Temperature() (drivers.Temperature, error)
|
||||
Humidity() (uint16, error)
|
||||
HumidityFloat() (float32, error)
|
||||
}
|
||||
@@ -49,23 +50,13 @@ func (t *device) ReadMeasurements() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Getter for temperature. Temperature method returns temperature as it is sent by device.
|
||||
// The temperature is measured temperature in Celsius multiplied by 10.
|
||||
// Getter for temperature. The temperature is returned in milli degrees Celsius.
|
||||
// If no successful measurements for this device was performed, returns UninitializedDataError.
|
||||
func (t *device) Temperature() (int16, error) {
|
||||
func (t *device) Temperature() (drivers.Temperature, error) {
|
||||
if !t.initialized {
|
||||
return 0, UninitializedDataError
|
||||
}
|
||||
return t.temperature, nil
|
||||
}
|
||||
|
||||
// Getter for temperature. TemperatureFloat returns temperature in a given scale.
|
||||
// If no successful measurements for this device was performed, returns UninitializedDataError.
|
||||
func (t *device) TemperatureFloat(scale TemperatureScale) (float32, error) {
|
||||
if !t.initialized {
|
||||
return 0, UninitializedDataError
|
||||
}
|
||||
return scale.convertToFloat(t.temperature), nil
|
||||
return drivers.Temperature(t.temperature) * 100, nil
|
||||
}
|
||||
|
||||
// Getter for humidity. Humidity returns humidity as it is sent by device.
|
||||
|
||||
@@ -9,6 +9,8 @@ package dht // import "tinygo.org/x/drivers/dht"
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device interface provides main functionality of the DHTXX sensors.
|
||||
@@ -35,10 +37,9 @@ func (m *managedDevice) Measurements() (temperature int16, humidity uint16, err
|
||||
return m.t.Measurements()
|
||||
}
|
||||
|
||||
// Getter for temperature. Temperature method returns temperature as it is sent by device.
|
||||
// The temperature is measured temperature in Celsius multiplied by 10.
|
||||
// Getter for temperature. The temperature is returned in milli degrees Celsius.
|
||||
// Depending on the UpdatePolicy of the device may update cached measurements.
|
||||
func (m *managedDevice) Temperature() (temp int16, err error) {
|
||||
func (m *managedDevice) Temperature() (temp drivers.Temperature, err error) {
|
||||
err = m.checkForUpdateOnDataRequest()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -64,16 +65,6 @@ func (m *managedDevice) checkForUpdateOnDataRequest() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Getter for temperature. TemperatureFloat returns temperature in a given scale.
|
||||
// Depending on the UpdatePolicy of the device may update cached measurements.
|
||||
func (m *managedDevice) TemperatureFloat(scale TemperatureScale) (float32, error) {
|
||||
err := m.checkForUpdateOnDataRequest()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return m.t.TemperatureFloat(scale)
|
||||
}
|
||||
|
||||
// Getter for humidity. Humidity returns humidity as it is sent by device.
|
||||
// The humidity is measured in percentages multiplied by 10.
|
||||
// Depending on the UpdatePolicy of the device may update cached measurements.
|
||||
|
||||
+2
-2
@@ -134,13 +134,13 @@ func (d *Device) ReadTime() (dt time.Time, err error) {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in millicelsius (mC)
|
||||
func (d *Device) ReadTemperature() (int32, error) {
|
||||
func (d *Device) ReadTemperature() (drivers.Temperature, error) {
|
||||
data := make([]uint8, 2)
|
||||
err := d.bus.ReadRegister(uint8(d.Address), REG_TEMP, data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(data[0])*1000 + int32((data[1]>>6)*25)*10, nil
|
||||
return drivers.Temperature(int32(data[0])*1000 + int32((data[1]>>6)*25)*10), nil
|
||||
}
|
||||
|
||||
// uint8ToBCD converts a byte to BCD for the DS3231
|
||||
|
||||
@@ -19,8 +19,8 @@ func main() {
|
||||
sensor.Configure()
|
||||
|
||||
for {
|
||||
temp := sensor.ReadTempF()
|
||||
fmt.Printf("temperature: %f\r\n", temp)
|
||||
temp, _ := sensor.ReadTemperature()
|
||||
fmt.Printf("temperature: %f°C\r\n", temp.Celsius())
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/apds9960"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
machine.I2C1.Configure(machine.I2CConfig{
|
||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
||||
Frequency: machine.TWI_FREQ_400KHZ,
|
||||
})
|
||||
|
||||
sensor := apds9960.New(machine.I2C1)
|
||||
|
||||
if !sensor.Connected() {
|
||||
println("APDS-9960 not connected!")
|
||||
return
|
||||
}
|
||||
|
||||
sensor.Configure(apds9960.Configuration{}) // use default settings
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/apds9960"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
machine.I2C1.Configure(machine.I2CConfig{
|
||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
||||
Frequency: machine.TWI_FREQ_400KHZ,
|
||||
})
|
||||
|
||||
sensor := apds9960.New(machine.I2C1)
|
||||
|
||||
if !sensor.Connected() {
|
||||
println("APDS-9960 not connected!")
|
||||
return
|
||||
}
|
||||
|
||||
sensor.Configure(apds9960.Configuration{}) // use default settings
|
||||
|
||||
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:
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/apds9960"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
machine.I2C1.Configure(machine.I2CConfig{
|
||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
||||
Frequency: machine.TWI_FREQ_400KHZ,
|
||||
})
|
||||
|
||||
sensor := apds9960.New(machine.I2C1)
|
||||
|
||||
if !sensor.Connected() {
|
||||
println("APDS-9960 not connected!")
|
||||
return
|
||||
}
|
||||
|
||||
sensor.Configure(apds9960.Configuration{}) // use default settings
|
||||
|
||||
sensor.EnableProximity() // enable proximity engine
|
||||
|
||||
for {
|
||||
|
||||
if sensor.ProximityAvailable() {
|
||||
p := sensor.ReadProximity()
|
||||
println("Proximity:", p)
|
||||
}
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func main() {
|
||||
|
||||
for {
|
||||
temp, _ := sensor.ReadTemperature()
|
||||
println("Temperature:", strconv.FormatFloat(float64(temp)/1000, 'f', 2, 64), "°C")
|
||||
println("Temperature:", strconv.FormatFloat(float64(temp.Celsius()), 'f', 2, 64), "°C")
|
||||
press, _ := sensor.ReadPressure()
|
||||
println("Pressure:", strconv.FormatFloat(float64(press)/100000, 'f', 2, 64), "hPa")
|
||||
hum, _ := sensor.ReadHumidity()
|
||||
|
||||
@@ -27,7 +27,7 @@ func main() {
|
||||
println("Error reading temperature", err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Temperature: %.2f °C\n", float32(t)/1000)
|
||||
fmt.Printf("Temperature: %.2f °C\n", t.Celsius())
|
||||
|
||||
accelX, accelY, accelZ, err := sensor.ReadAcceleration()
|
||||
if err != nil {
|
||||
|
||||
@@ -22,7 +22,7 @@ func main() {
|
||||
|
||||
for {
|
||||
temp, _ := sensor.ReadTemperature()
|
||||
println("Temperature:", float32(temp)/1000, "°C")
|
||||
println("Temperature:", temp.Celsius(), "°C")
|
||||
|
||||
pressure, _ := sensor.ReadPressure()
|
||||
println("Pressure", float32(pressure)/100000, "hPa")
|
||||
|
||||
@@ -30,7 +30,7 @@ func main() {
|
||||
println("Error reading temperature")
|
||||
}
|
||||
// Temperature in degrees Celsius
|
||||
fmt.Printf("Temperature: %.2f °C\n", float32(t)/1000)
|
||||
fmt.Printf("Temperature: %.2f °C\n", t.Celsius())
|
||||
|
||||
p, err := sensor.ReadPressure()
|
||||
if err != nil {
|
||||
|
||||
@@ -38,13 +38,13 @@ func main() {
|
||||
}
|
||||
|
||||
for {
|
||||
temp, err := sensor.ReadTemperature() // returns the temperature in centicelsius
|
||||
temp, err := sensor.ReadTemperature() // returns the temperature in millicelsius
|
||||
press, err := sensor.ReadPressure() // returns the pressure in centipascals
|
||||
|
||||
if err != nil {
|
||||
println(err)
|
||||
} else {
|
||||
println("Temperature: " + strconv.FormatInt(int64(temp), 10) + " cC")
|
||||
println("Temperature:", temp/1000, "C")
|
||||
println("Pressure: " + strconv.FormatInt(int64(press), 10) + " cPa\n")
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ func main() {
|
||||
fmt.Printf("Date: %d/%s/%02d %02d:%02d:%02d \r\n", dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), dt.Second())
|
||||
}
|
||||
temp, _ := rtc.ReadTemperature()
|
||||
fmt.Printf("Temperature: %.2f °C \r\n", float32(temp)/1000)
|
||||
fmt.Printf("Temperature: %.2f °C \r\n", temp.Celsius())
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/hts221"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
machine.I2C1.Configure(machine.I2CConfig{
|
||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
||||
Frequency: machine.TWI_FREQ_400KHZ,
|
||||
})
|
||||
|
||||
sensor := hts221.New(machine.I2C1)
|
||||
|
||||
if !sensor.Connected() {
|
||||
println("HTS221 not connected!")
|
||||
return
|
||||
}
|
||||
|
||||
sensor.Configure() // power on and calibrate
|
||||
|
||||
for {
|
||||
|
||||
h, _ := sensor.ReadHumidity()
|
||||
t, _ := sensor.ReadTemperature()
|
||||
println("h =", float32(h)/100.0, "% / t =", float32(t)/1000.0, "*C")
|
||||
time.Sleep(time.Second)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//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,
|
||||
})
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
|
||||
"tinygo.org/x/drivers/ili9341"
|
||||
)
|
||||
|
||||
@@ -16,15 +16,16 @@ 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)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//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
|
||||
)
|
||||
+12
-21
@@ -1,7 +1,7 @@
|
||||
//go:build wioterminal
|
||||
// +build wioterminal
|
||||
|
||||
package initdisplay
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
@@ -9,31 +9,22 @@ import (
|
||||
"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(
|
||||
var (
|
||||
display = ili9341.NewSPI(
|
||||
machine.SPI3,
|
||||
machine.LCD_DC,
|
||||
machine.LCD_SS_PIN,
|
||||
machine.LCD_RESET,
|
||||
)
|
||||
|
||||
// configure display
|
||||
display.Configure(ili9341.Config{})
|
||||
backlight = machine.LCD_BACKLIGHT
|
||||
)
|
||||
|
||||
backlight.High()
|
||||
|
||||
display.SetRotation(ili9341.Rotation270)
|
||||
|
||||
return display
|
||||
func init() {
|
||||
machine.SPI3.Configure(machine.SPIConfig{
|
||||
SCK: machine.LCD_SCK_PIN,
|
||||
SDO: machine.LCD_SDO_PIN,
|
||||
SDI: machine.LCD_SDI_PIN,
|
||||
Frequency: 40000000,
|
||||
})
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
//go:build atsamd21
|
||||
// +build atsamd21
|
||||
|
||||
package initdisplay
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"tinygo.org/x/drivers/ili9341"
|
||||
)
|
||||
|
||||
var ()
|
||||
|
||||
func InitDisplay() *ili9341.Device {
|
||||
machine.SPI0.Configure(machine.SPIConfig{
|
||||
SCK: machine.SPI0_SCK_PIN,
|
||||
SDO: machine.SPI0_SDO_PIN,
|
||||
SDI: machine.SPI0_SDI_PIN,
|
||||
Frequency: 24000000,
|
||||
})
|
||||
|
||||
// configure backlight
|
||||
backlight := machine.D3
|
||||
backlight.Configure(machine.PinConfig{machine.PinOutput})
|
||||
|
||||
display := ili9341.NewSPI(
|
||||
machine.SPI0,
|
||||
machine.D0,
|
||||
machine.D1,
|
||||
machine.D2,
|
||||
)
|
||||
|
||||
// configure display
|
||||
display.Configure(ili9341.Config{})
|
||||
|
||||
backlight.High()
|
||||
|
||||
display.SetRotation(ili9341.Rotation270)
|
||||
|
||||
return display
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
//go:build pyportal
|
||||
// +build pyportal
|
||||
|
||||
package initdisplay
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"tinygo.org/x/drivers/ili9341"
|
||||
)
|
||||
|
||||
func InitDisplay() *ili9341.Device {
|
||||
display := ili9341.NewParallel(
|
||||
machine.LCD_DATA0,
|
||||
machine.TFT_WR,
|
||||
machine.TFT_DC,
|
||||
machine.TFT_CS,
|
||||
machine.TFT_RESET,
|
||||
machine.TFT_RD,
|
||||
)
|
||||
|
||||
// configure backlight
|
||||
backlight := machine.TFT_BACKLIGHT
|
||||
backlight.Configure(machine.PinConfig{machine.PinOutput})
|
||||
|
||||
// configure display
|
||||
display.Configure(ili9341.Config{})
|
||||
|
||||
backlight.High()
|
||||
|
||||
display.SetRotation(ili9341.Rotation270)
|
||||
|
||||
return display
|
||||
}
|
||||
@@ -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,17 +44,20 @@ 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()
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//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
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
//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,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//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,
|
||||
})
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
|
||||
"tinygo.org/x/drivers/ili9341"
|
||||
)
|
||||
|
||||
@@ -16,15 +16,16 @@ 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)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//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
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
//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,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//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,
|
||||
})
|
||||
}
|
||||
@@ -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,10 +20,6 @@ var (
|
||||
green = color.RGBA{0, 255, 0, 255}
|
||||
)
|
||||
|
||||
var (
|
||||
display *ili9341.Device
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
for err != nil {
|
||||
@@ -32,7 +28,9 @@ func main() {
|
||||
}
|
||||
|
||||
func run() error {
|
||||
display = initdisplay.InitDisplay()
|
||||
backlight.Configure(machine.PinConfig{machine.PinOutput})
|
||||
|
||||
display.Configure(ili9341.Config{})
|
||||
|
||||
width, height := display.Size()
|
||||
if width < 320 || height < 240 {
|
||||
@@ -40,6 +38,7 @@ func run() error {
|
||||
}
|
||||
|
||||
display.FillScreen(black)
|
||||
backlight.High()
|
||||
|
||||
for {
|
||||
err := drawJpeg(display)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//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
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
//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,
|
||||
})
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/lps22hb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
machine.I2C1.Configure(machine.I2CConfig{
|
||||
SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense
|
||||
SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense
|
||||
Frequency: machine.TWI_FREQ_400KHZ,
|
||||
})
|
||||
|
||||
sensor := lps22hb.New(machine.I2C1)
|
||||
|
||||
if !sensor.Connected() {
|
||||
println("LPS22HB not connected!")
|
||||
return
|
||||
}
|
||||
|
||||
sensor.Configure()
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,8 +23,8 @@ func main() {
|
||||
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")
|
||||
t, _ := accel.ReadTemperature()
|
||||
println("Degrees C", t.Celsius(), "\n\n")
|
||||
time.Sleep(time.Millisecond * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/lsm6dsox"
|
||||
)
|
||||
|
||||
@@ -76,7 +77,7 @@ func calibrateGyro(device *lsm6dsox.Device) {
|
||||
}
|
||||
|
||||
// Arduino IDE's Serial Plotter
|
||||
func printPlotter(ax, ay, az, gx, gy, gz, t int32) {
|
||||
func printPlotter(ax, ay, az, gx, gy, gz int32, t drivers.Temperature) {
|
||||
if SHOW_ACCELERATION {
|
||||
fmt.Printf("AX:%f, AY:%f, AZ:%f,", axis(ax, 0), axis(ay, 0), axis(az, 0))
|
||||
}
|
||||
@@ -84,7 +85,7 @@ func printPlotter(ax, ay, az, gx, gy, gz, t int32) {
|
||||
fmt.Printf("GX:%f, GY:%f, GZ:%f,", axis(gx, cal[0]), axis(gy, cal[1]), axis(gz, cal[2]))
|
||||
}
|
||||
if SHOW_TEMPERATURE {
|
||||
fmt.Printf("T:%f", float32(t)/1000)
|
||||
fmt.Printf("T:%f", t.Celsius())
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// LSM9DS1, 9 axis Inertial Measurement Unit (IMU)
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/lsm9ds1"
|
||||
)
|
||||
|
||||
const (
|
||||
PLOTTER = false
|
||||
SHOW_ACCELERATION = true
|
||||
SHOW_ROTATION = true
|
||||
SHOW_MAGNETIC_FIELD = true
|
||||
SHOW_TEMPERATURE = true
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// I2C configure
|
||||
machine.I2C0.Configure(machine.I2CConfig{})
|
||||
|
||||
// LSM9DS1 setup
|
||||
device := lsm9ds1.New(machine.I2C0)
|
||||
err := device.Configure(lsm9ds1.Configuration{
|
||||
AccelRange: lsm9ds1.ACCEL_2G,
|
||||
AccelSampleRate: lsm9ds1.ACCEL_SR_119,
|
||||
GyroRange: lsm9ds1.GYRO_250DPS,
|
||||
GyroSampleRate: lsm9ds1.GYRO_SR_119,
|
||||
MagRange: lsm9ds1.MAG_4G,
|
||||
MagSampleRate: lsm9ds1.MAG_SR_40,
|
||||
})
|
||||
if err != nil {
|
||||
for {
|
||||
println("Failed to configure", err.Error())
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
if con, err := device.Connected(); !con || err != nil {
|
||||
println("LSM9DS1 not connected")
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
ax, ay, az, _ := device.ReadAcceleration()
|
||||
gx, gy, gz, _ := device.ReadRotation()
|
||||
mx, my, mz, _ := device.ReadMagneticField()
|
||||
t, _ := device.ReadTemperature()
|
||||
|
||||
if PLOTTER {
|
||||
printPlotter(ax, ay, az, gx, gy, gz, mx, my, mz, t)
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
} else {
|
||||
printMonitor(ax, ay, az, gx, gy, gz, mx, my, mz, t)
|
||||
time.Sleep(time.Millisecond * 1000)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Arduino IDE's Serial Plotter
|
||||
func printPlotter(ax, ay, az, gx, gy, gz, mx, my, mz, t int32) {
|
||||
if SHOW_ACCELERATION {
|
||||
fmt.Printf("AX:%f, AY:%f, AZ:%f,", axis(ax), axis(ay), axis(az))
|
||||
}
|
||||
if SHOW_ROTATION {
|
||||
fmt.Printf("GX:%f, GY:%f, GZ:%f,", axis(gx), axis(gy), axis(gz))
|
||||
}
|
||||
if SHOW_MAGNETIC_FIELD {
|
||||
fmt.Printf("MX:%d, MY:%d, MZ:%d,", mx, my, mz)
|
||||
}
|
||||
if SHOW_TEMPERATURE {
|
||||
fmt.Printf("T:%f", float32(t)/1000)
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
// Any Serial Monitor
|
||||
func printMonitor(ax, ay, az, gx, gy, gz, mx, my, mz, t int32) {
|
||||
if SHOW_ACCELERATION {
|
||||
fmt.Printf("Acceleration (g): %f, %f, %f\r\n", axis(ax), axis(ay), axis(az))
|
||||
}
|
||||
if SHOW_ROTATION {
|
||||
fmt.Printf("Rotation (dps): %f, %f, %f\r\n", axis(gx), axis(gy), axis(gz))
|
||||
}
|
||||
if SHOW_MAGNETIC_FIELD {
|
||||
fmt.Printf("Magnetic field (nT): %d, %d, %d\r\n", mx, my, mz)
|
||||
}
|
||||
if SHOW_TEMPERATURE {
|
||||
fmt.Printf("Temperature C: %f\r\n", float32(t)/1000)
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
func axis(raw int32) float32 {
|
||||
return float32(raw) / 1000000
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func main() {
|
||||
println("Magnetic readings:", x, y, z)
|
||||
|
||||
c, _ := mag.ReadTemperature()
|
||||
println("Temperature:", float32(c)/1000, "°C")
|
||||
println("Temperature:", c.Celsius(), "°C")
|
||||
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func main() {
|
||||
|
||||
temp, _ := thermo.ReadTemperature()
|
||||
|
||||
print(fmt.Sprintf("%.2f°C\r\n", float32(temp)/1000.0))
|
||||
print(fmt.Sprintf("%.2f°C\r\n", temp.Celsius()))
|
||||
|
||||
time.Sleep(time.Millisecond * 1000)
|
||||
}
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
//go:build nano_rp2040
|
||||
// +build nano_rp2040
|
||||
|
||||
// This examples shows how to control RGB LED connected to
|
||||
// NINA-W102 chip on Arduino Nano RP2040 Connect board
|
||||
// Built-in LED code added for API comparison
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/wifinina"
|
||||
)
|
||||
|
||||
const (
|
||||
LED = machine.LED
|
||||
|
||||
// Arduino Nano RP2040 Connect board RGB LED pins
|
||||
// See https://docs.arduino.cc/static/3525d638b5c76a2d19588d6b41cd02a0/ABX00053-full-pinout.pdf
|
||||
LED_R wifinina.Pin = 27
|
||||
LED_G wifinina.Pin = 25
|
||||
LED_B wifinina.Pin = 26
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
// these are the default pins for the Arduino Nano-RP2040 Connect
|
||||
spi = machine.NINA_SPI
|
||||
|
||||
// this is the ESP chip that has the WIFININA firmware flashed on it
|
||||
device *wifinina.Device
|
||||
)
|
||||
|
||||
func setup() {
|
||||
|
||||
// Configure SPI for 8Mhz, Mode 0, MSB First
|
||||
spi.Configure(machine.SPIConfig{
|
||||
Frequency: 8 * 1e6,
|
||||
SDO: machine.NINA_SDO,
|
||||
SDI: machine.NINA_SDI,
|
||||
SCK: machine.NINA_SCK,
|
||||
})
|
||||
|
||||
device = wifinina.New(spi,
|
||||
machine.NINA_CS,
|
||||
machine.NINA_ACK,
|
||||
machine.NINA_GPIO0,
|
||||
machine.NINA_RESETN)
|
||||
device.Configure()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
LED_R.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
|
||||
LED_G.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
|
||||
LED_B.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
setup()
|
||||
|
||||
LED.Low() // OFF
|
||||
LED_R.High() // OFF
|
||||
LED_G.High() // OFF
|
||||
LED_B.High() // OFF
|
||||
|
||||
go func() {
|
||||
for {
|
||||
LED.Low()
|
||||
time.Sleep(time.Second)
|
||||
LED.High()
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
LED_R.Low() // ON
|
||||
time.Sleep(time.Second)
|
||||
LED_R.High() // OFF
|
||||
LED_G.Low() // ON
|
||||
time.Sleep(time.Second)
|
||||
LED_G.High() // OFF
|
||||
LED_B.Low() // ON
|
||||
time.Sleep(time.Second)
|
||||
LED_B.High() // OFF
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
// Package hts221 implements a driver for HTS221,
|
||||
// a capacitive digital sensor for relative humidity and temperature.
|
||||
//
|
||||
// Datasheet: https://www.st.com/resource/en/datasheet/hts221.pdf
|
||||
//
|
||||
package hts221
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device wraps an I2C connection to a HTS221 device.
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
Address uint8
|
||||
humiditySlope float32
|
||||
humidityZero float32
|
||||
temperatureSlope float32
|
||||
temperatureZero float32
|
||||
}
|
||||
|
||||
// Connected returns whether HTS221 has been found.
|
||||
// It does a "who am I" request and checks the response.
|
||||
func (d *Device) Connected() bool {
|
||||
data := []byte{0}
|
||||
d.bus.ReadRegister(d.Address, HTS221_WHO_AM_I_REG, data)
|
||||
return data[0] == 0xBC
|
||||
}
|
||||
|
||||
// Configure sets up the HTS221 device for communication.
|
||||
func (d *Device) Configure() {
|
||||
// read calibration data
|
||||
d.calibration()
|
||||
// activate device and use block data update mode
|
||||
d.Power(true)
|
||||
}
|
||||
|
||||
// Power is for turn on/off the HTS221 device
|
||||
func (d *Device) Power(status bool) {
|
||||
data := []byte{0}
|
||||
if status {
|
||||
data[0] = 0x84
|
||||
}
|
||||
d.bus.WriteRegister(d.Address, HTS221_CTRL1_REG, data)
|
||||
}
|
||||
|
||||
// ReadHumidity returns the relative humidity in percent * 100.
|
||||
// Returns an error if the device is not turned on.
|
||||
func (d *Device) ReadHumidity() (humidity int32, err error) {
|
||||
err = d.waitForOneShot(0x02)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// read data and calibrate
|
||||
data := []byte{0, 0}
|
||||
d.bus.ReadRegister(d.Address, HTS221_HUMID_OUT_REG, data[:1])
|
||||
d.bus.ReadRegister(d.Address, HTS221_HUMID_OUT_REG+1, data[1:])
|
||||
hValue := readInt(data[1], data[0])
|
||||
hValueCalib := float32(hValue)*d.humiditySlope + d.humidityZero
|
||||
|
||||
return int32(hValueCalib * 100), nil
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||
// Returns an error if the device is not turned on.
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
err = d.waitForOneShot(0x01)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// read data and calibrate
|
||||
data := []byte{0, 0}
|
||||
d.bus.ReadRegister(d.Address, HTS221_TEMP_OUT_REG, data[:1])
|
||||
d.bus.ReadRegister(d.Address, HTS221_TEMP_OUT_REG+1, data[1:])
|
||||
tValue := readInt(data[1], data[0])
|
||||
tValueCalib := float32(tValue)*d.temperatureSlope + d.temperatureZero
|
||||
|
||||
return int32(tValueCalib * 1000), nil
|
||||
}
|
||||
|
||||
// Resolution sets the HTS221's resolution mode.
|
||||
// The higher resolutions are more accurate but comsume more power (see datasheet).
|
||||
// The number of averaged samples will be (h + 2) ^ 2, (t + 1) ^ 2
|
||||
//
|
||||
func (d *Device) Resolution(h uint8, t uint8) {
|
||||
if h > 7 {
|
||||
h = 3 // default
|
||||
}
|
||||
if t > 7 {
|
||||
t = 3 // default
|
||||
}
|
||||
d.bus.WriteRegister(d.Address, HTS221_AV_CONF_REG, []byte{h<<3 | t})
|
||||
}
|
||||
|
||||
// private functions
|
||||
|
||||
// read factory calibration data
|
||||
func (d *Device) calibration() {
|
||||
h0rH, h1rH := []byte{0}, []byte{0}
|
||||
t0degC, t1degC := []byte{0}, []byte{0}
|
||||
t1t0msb := []byte{0}
|
||||
h0t0Out, h1t0Out := []byte{0, 0}, []byte{0, 0}
|
||||
t0Out, t1Out := []byte{0, 0}, []byte{0, 0}
|
||||
|
||||
d.bus.ReadRegister(d.Address, HTS221_H0_rH_x2_REG, h0rH)
|
||||
d.bus.ReadRegister(d.Address, HTS221_H1_rH_x2_REG, h1rH)
|
||||
d.bus.ReadRegister(d.Address, HTS221_T0_degC_x8_REG, t0degC)
|
||||
d.bus.ReadRegister(d.Address, HTS221_T1_degC_x8_REG, t1degC)
|
||||
d.bus.ReadRegister(d.Address, HTS221_T1_T0_MSB_REG, t1t0msb)
|
||||
d.bus.ReadRegister(d.Address, HTS221_H0_T0_OUT_REG, h0t0Out[:1])
|
||||
d.bus.ReadRegister(d.Address, HTS221_H0_T0_OUT_REG+1, h0t0Out[1:])
|
||||
d.bus.ReadRegister(d.Address, HTS221_H1_T0_OUT_REG, h1t0Out[:1])
|
||||
d.bus.ReadRegister(d.Address, HTS221_H1_T0_OUT_REG+1, h1t0Out[1:])
|
||||
d.bus.ReadRegister(d.Address, HTS221_T0_OUT_REG, t0Out[:1])
|
||||
d.bus.ReadRegister(d.Address, HTS221_T0_OUT_REG+1, t0Out[1:])
|
||||
d.bus.ReadRegister(d.Address, HTS221_T1_OUT_REG, t1Out[:1])
|
||||
d.bus.ReadRegister(d.Address, HTS221_T1_OUT_REG+1, t1Out[1:])
|
||||
|
||||
h0rH_v := float32(h0rH[0]) / 2.0
|
||||
h1rH_v := float32(h1rH[0]) / 2.0
|
||||
t0degC_v := float32(readUint(t1t0msb[0]&0x03, t0degC[0])) / 8.0
|
||||
t1degC_v := float32(readUint(t1t0msb[0]&0x0C>>2, t1degC[0])) / 8.0
|
||||
h0t0Out_v := float32(readInt(h0t0Out[1], h0t0Out[0]))
|
||||
h1t0Out_v := float32(readInt(h1t0Out[1], h1t0Out[0]))
|
||||
t0Out_v := float32(readInt(t0Out[1], t0Out[0]))
|
||||
t1Out_v := float32(readInt(t1Out[1], t1Out[0]))
|
||||
|
||||
d.humiditySlope = (h1rH_v - h0rH_v) / (h1t0Out_v - h0t0Out_v)
|
||||
d.humidityZero = h0rH_v - d.humiditySlope*h0t0Out_v
|
||||
d.temperatureSlope = (t1degC_v - t0degC_v) / (t1Out_v - t0Out_v)
|
||||
d.temperatureZero = t0degC_v - d.temperatureSlope*t0Out_v
|
||||
}
|
||||
|
||||
// wait and trigger one shot in block update
|
||||
func (d *Device) waitForOneShot(filter uint8) error {
|
||||
data := []byte{0}
|
||||
|
||||
// check if the device is on
|
||||
d.bus.ReadRegister(d.Address, HTS221_CTRL1_REG, data)
|
||||
if data[0]&0x80 == 0 {
|
||||
return errors.New("device is off, unable to query")
|
||||
}
|
||||
|
||||
// wait until one shot (one conversion) is ready to go
|
||||
data[0] = 1
|
||||
for {
|
||||
d.bus.ReadRegister(d.Address, HTS221_CTRL2_REG, data)
|
||||
if data[0]&0x01 == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// trigger one shot
|
||||
d.bus.WriteRegister(d.Address, HTS221_CTRL2_REG, []byte{0x01})
|
||||
|
||||
// wait until conversion completed
|
||||
data[0] = 0
|
||||
for {
|
||||
d.bus.ReadRegister(d.Address, HTS221_STATUS_REG, data)
|
||||
if data[0]&filter == filter {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readUint(msb byte, lsb byte) uint16 {
|
||||
return uint16(msb)<<8 | uint16(lsb)
|
||||
}
|
||||
|
||||
func readInt(msb byte, lsb byte) int16 {
|
||||
return int16(uint16(msb)<<8 | uint16(lsb))
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
//go:build !nano_33_ble
|
||||
// +build !nano_33_ble
|
||||
|
||||
package hts221
|
||||
|
||||
import "tinygo.org/x/drivers"
|
||||
|
||||
// New creates a new HTS221 connection. The I2C bus must already be
|
||||
// configured.
|
||||
//
|
||||
// This function only creates the Device object, it does not touch the device.
|
||||
func New(bus drivers.I2C) Device {
|
||||
return Device{bus: bus, Address: HTS221_ADDRESS}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
//go:build nano_33_ble
|
||||
// +build nano_33_ble
|
||||
|
||||
package hts221
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// New creates a new HTS221 connection. The I2C bus must already be
|
||||
// configured.
|
||||
//
|
||||
// This function only creates the Device object, it does not touch the device.
|
||||
func New(bus drivers.I2C) Device {
|
||||
// turn on internal power pin (machine.P0_22) and I2C1 pullups power pin (machine.P1_00)
|
||||
// and wait a moment.
|
||||
ENV := machine.P0_22
|
||||
ENV.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
ENV.High()
|
||||
R := machine.P1_00
|
||||
R.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
R.High()
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
|
||||
return Device{bus: bus, Address: HTS221_ADDRESS}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package hts221
|
||||
|
||||
const (
|
||||
|
||||
// I2C address
|
||||
HTS221_ADDRESS = 0x5F
|
||||
|
||||
// control/status registers
|
||||
HTS221_WHO_AM_I_REG = 0x0F
|
||||
HTS221_AV_CONF_REG = 0x10
|
||||
HTS221_CTRL1_REG = 0x20
|
||||
HTS221_CTRL2_REG = 0x21
|
||||
HTS221_STATUS_REG = 0x27
|
||||
HTS221_HUMID_OUT_REG = 0x28
|
||||
HTS221_TEMP_OUT_REG = 0x2A
|
||||
|
||||
// calibration registers
|
||||
HTS221_H0_rH_x2_REG = 0x30
|
||||
HTS221_H1_rH_x2_REG = 0x31
|
||||
HTS221_T0_degC_x8_REG = 0x32
|
||||
HTS221_T1_degC_x8_REG = 0x33
|
||||
HTS221_T1_T0_MSB_REG = 0x35
|
||||
HTS221_H0_T0_OUT_REG = 0x36
|
||||
HTS221_H1_T0_OUT_REG = 0x3A
|
||||
HTS221_T0_OUT_REG = 0x3C
|
||||
HTS221_T1_OUT_REG = 0x3E
|
||||
)
|
||||
@@ -1,280 +0,0 @@
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"machine"
|
||||
)
|
||||
|
||||
// I2C is an I2C implementation by Software. Since it is implemented by
|
||||
// software, it can be used with microcontrollers that do not have I2C
|
||||
// function. This is not efficient but works around broken or missing drivers.
|
||||
type I2C struct {
|
||||
scl machine.Pin
|
||||
sda machine.Pin
|
||||
nack bool
|
||||
baudrate uint32
|
||||
}
|
||||
|
||||
// I2CConfig is used to store config info for I2C.
|
||||
type I2CConfig struct {
|
||||
Frequency uint32
|
||||
SCL machine.Pin
|
||||
SDA machine.Pin
|
||||
}
|
||||
|
||||
var (
|
||||
errSI2CAckExpected = errors.New("I2C error: expected ACK not NACK")
|
||||
)
|
||||
|
||||
// New returns the i2csoft driver. For the arguments, specify the pins to be
|
||||
// used as SCL and SDA. As I2C is implemented in software, any GPIO pin can be
|
||||
// specified.
|
||||
func New(sclPin, sdaPin machine.Pin) *I2C {
|
||||
return &I2C{
|
||||
scl: sclPin,
|
||||
sda: sdaPin,
|
||||
baudrate: 100e3,
|
||||
}
|
||||
}
|
||||
|
||||
// Configure is intended to setup the I2C interface.
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
// Default I2C bus speed is 100 kHz.
|
||||
if config.Frequency != 0 {
|
||||
i2c.SetBaudRate(config.Frequency)
|
||||
}
|
||||
|
||||
// This exists for compatibility with machine.I2CConfig. SCL and SDA must
|
||||
// be set at the same time. Because Pin(0) is sometimes set, it is not
|
||||
// checked for 0.
|
||||
if config.SCL != config.SDA {
|
||||
i2c.scl = config.SCL
|
||||
i2c.sda = config.SDA
|
||||
}
|
||||
|
||||
// enable pins
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
i2c.sda.High()
|
||||
i2c.scl.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
i2c.scl.High()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the communication speed for the I2C.
|
||||
func (i2c *I2C) SetBaudRate(br uint32) {
|
||||
// At this time, the value of i2c.baudrate is ignored because it is fixed
|
||||
// at 100 kHz. SetBaudrate() is exist for compatibility with machine.I2C.
|
||||
i2c.baudrate = br
|
||||
}
|
||||
|
||||
// Tx does a single I2C transaction at the specified address.
|
||||
// It clocks out the given address, writes the bytes in w, reads back len(r)
|
||||
// bytes and stores them in r, and generates a stop condition on the bus.
|
||||
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
||||
i2c.nack = false
|
||||
if len(w) != 0 {
|
||||
// send start/address for write
|
||||
i2c.sendAddress(addr, true)
|
||||
|
||||
// wait until transmission complete
|
||||
|
||||
// ACK received (0: ACK, 1: NACK)
|
||||
if i2c.nack {
|
||||
i2c.signalStop()
|
||||
return errSI2CAckExpected
|
||||
}
|
||||
|
||||
// write data
|
||||
for _, b := range w {
|
||||
i2c.writeByte(b)
|
||||
}
|
||||
|
||||
i2c.signalStop()
|
||||
}
|
||||
if len(r) != 0 {
|
||||
// send start/address for read
|
||||
i2c.sendAddress(addr, false)
|
||||
|
||||
// wait transmission complete
|
||||
|
||||
// ACK received (0: ACK, 1: NACK)
|
||||
if i2c.nack {
|
||||
i2c.signalStop()
|
||||
return errSI2CAckExpected
|
||||
}
|
||||
|
||||
// read first byte
|
||||
r[0] = i2c.readByte()
|
||||
for i := 1; i < len(r); i++ {
|
||||
// Send an ACK
|
||||
|
||||
i2c.signalRead()
|
||||
|
||||
// Read data and send the ACK
|
||||
r[i] = i2c.readByte()
|
||||
}
|
||||
|
||||
// Send NACK to end transmission
|
||||
i2c.sendNack()
|
||||
|
||||
i2c.signalStop()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeByte writes a single byte to the I2C bus.
|
||||
func (i2c *I2C) writeByte(data byte) {
|
||||
// Send data byte
|
||||
i2c.scl.Low()
|
||||
i2c.sda.High()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
i2c.wait()
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
i2c.scl.Low()
|
||||
if ((data >> (7 - i)) & 1) == 1 {
|
||||
i2c.sda.High()
|
||||
} else {
|
||||
i2c.sda.Low()
|
||||
}
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
}
|
||||
|
||||
i2c.scl.Low()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
|
||||
i2c.nack = i2c.sda.Get()
|
||||
|
||||
i2c.wait()
|
||||
|
||||
// wait until transmission successful
|
||||
}
|
||||
|
||||
// sendAddress sends the address and start signal
|
||||
func (i2c *I2C) sendAddress(address uint16, write bool) {
|
||||
data := (address << 1)
|
||||
if !write {
|
||||
data |= 1 // set read flag
|
||||
}
|
||||
|
||||
i2c.scl.High()
|
||||
i2c.sda.Low()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
for i := 0; i < 8; i++ {
|
||||
i2c.scl.Low()
|
||||
if ((data >> (7 - i)) & 1) == 1 {
|
||||
i2c.sda.High()
|
||||
} else {
|
||||
i2c.sda.Low()
|
||||
}
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
}
|
||||
|
||||
i2c.scl.Low()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
|
||||
i2c.nack = i2c.sda.Get()
|
||||
|
||||
i2c.wait()
|
||||
|
||||
// wait until bus ready
|
||||
}
|
||||
|
||||
func (i2c *I2C) signalStop() {
|
||||
i2c.scl.Low()
|
||||
i2c.sda.Low()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.sda.High()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
}
|
||||
|
||||
func (i2c *I2C) signalRead() {
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.Low()
|
||||
i2c.sda.Low()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
}
|
||||
|
||||
func (i2c *I2C) readByte() byte {
|
||||
var data byte
|
||||
for i := 0; i < 8; i++ {
|
||||
i2c.scl.Low()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.High()
|
||||
if i2c.sda.Get() {
|
||||
data |= 1 << (7 - i)
|
||||
}
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (i2c *I2C) sendNack() {
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.Low()
|
||||
i2c.sda.High()
|
||||
i2c.sda.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
i2c.scl.High()
|
||||
i2c.wait()
|
||||
i2c.wait()
|
||||
}
|
||||
|
||||
// WriteRegister transmits first the register and then the data to the
|
||||
// peripheral device.
|
||||
//
|
||||
// Many I2C-compatible devices are organized in terms of registers. This method
|
||||
// is a shortcut to easily write to such registers. Also, it only works for
|
||||
// devices with 7-bit addresses, which is the vast majority.
|
||||
func (i2c *I2C) WriteRegister(address uint8, register uint8, data []byte) error {
|
||||
buf := make([]uint8, len(data)+1)
|
||||
buf[0] = register
|
||||
copy(buf[1:], data)
|
||||
return i2c.Tx(uint16(address), buf, nil)
|
||||
}
|
||||
|
||||
// ReadRegister transmits the register, restarts the connection as a read
|
||||
// operation, and reads the response.
|
||||
//
|
||||
// Many I2C-compatible devices are organized in terms of registers. This method
|
||||
// is a shortcut to easily read such registers. Also, it only works for devices
|
||||
// with 7-bit addresses, which is the vast majority.
|
||||
func (i2c *I2C) ReadRegister(address uint8, register uint8, data []byte) error {
|
||||
return i2c.Tx(uint16(address), []byte{register}, data)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//go:build atsamd51 || atsame5x
|
||||
// +build atsamd51 atsame5x
|
||||
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"device"
|
||||
)
|
||||
|
||||
// wait waits for half the time of the SCL operation interval. It is set to
|
||||
// about 100 kHz.
|
||||
func (i2c *I2C) wait() {
|
||||
wait := 20
|
||||
for i := 0; i < wait; i++ {
|
||||
device.Asm(`nop`)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//go:build esp32
|
||||
// +build esp32
|
||||
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"device"
|
||||
)
|
||||
|
||||
// wait waits for half the time of the SCL operation interval. It is set to
|
||||
// about 100 kHz.
|
||||
func (i2c *I2C) wait() {
|
||||
wait := 60
|
||||
for i := 0; i < wait; i++ {
|
||||
device.Asm(`nop`)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//go:build nrf52840
|
||||
// +build nrf52840
|
||||
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"device"
|
||||
)
|
||||
|
||||
// wait waits for half the time of the SCL operation interval. It is set to
|
||||
// about 100 kHz.
|
||||
func (i2c *I2C) wait() {
|
||||
wait := 26
|
||||
for i := 0; i < wait; i++ {
|
||||
device.Asm(`nop`)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
//go:build !esp32 && !atsamd51 && !atsame5x && !stm32f4 && !rp2040 && !nrf52840
|
||||
// +build !esp32,!atsamd51,!atsame5x,!stm32f4,!rp2040,!nrf52840
|
||||
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"device"
|
||||
)
|
||||
|
||||
// wait waits for half the time of the SCL operation interval.
|
||||
func (i2c *I2C) wait() {
|
||||
wait := 20
|
||||
for i := 0; i < wait; i++ {
|
||||
device.Asm(`nop`)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//go:build rp2040
|
||||
// +build rp2040
|
||||
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"device"
|
||||
)
|
||||
|
||||
// wait waits for half the time of the SCL operation interval. It is set to
|
||||
// about 100 kHz.
|
||||
func (i2c *I2C) wait() {
|
||||
wait := 50
|
||||
for i := 0; i < wait; i++ {
|
||||
device.Asm(`nop`)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//go:build stm32f4
|
||||
// +build stm32f4
|
||||
|
||||
package i2csoft
|
||||
|
||||
import (
|
||||
"device"
|
||||
)
|
||||
|
||||
// wait waits for half the time of the SCL operation interval. It is set to
|
||||
// about 100 kHz.
|
||||
func (i2c *I2C) wait() {
|
||||
wait := 77
|
||||
for i := 0; i < wait; i++ {
|
||||
device.Asm(`nop`)
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Package lps22hb implements a driver for LPS22HB, a MEMS nano pressure sensor.
|
||||
//
|
||||
// Datasheet: https://www.st.com/resource/en/datasheet/dm00140895.pdf
|
||||
//
|
||||
package lps22hb
|
||||
|
||||
import (
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device wraps an I2C connection to a HTS221 device.
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
Address uint8
|
||||
}
|
||||
|
||||
// Connected returns whether LPS22HB has been found.
|
||||
// It does a "who am I" request and checks the response.
|
||||
func (d *Device) Connected() bool {
|
||||
data := []byte{0}
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_WHO_AM_I_REG, data)
|
||||
return data[0] == 0xB1
|
||||
}
|
||||
|
||||
// Configure sets up the LPS22HB device for communication.
|
||||
func (d *Device) Configure() {
|
||||
// set to block update mode
|
||||
d.bus.WriteRegister(d.Address, LPS22HB_CTRL1_REG, []byte{0x02})
|
||||
}
|
||||
|
||||
// ReadPressure returns the pressure in milli pascals (mPa).
|
||||
func (d *Device) ReadPressure() (pressure int32, err error) {
|
||||
d.waitForOneShot()
|
||||
|
||||
// read data
|
||||
data := []byte{0, 0, 0}
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_PRESS_OUT_REG, data[:1])
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_PRESS_OUT_REG+1, data[1:2])
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_PRESS_OUT_REG+2, data[2:])
|
||||
pValue := float32(uint32(data[2])<<16|uint32(data[1])<<8|uint32(data[0])) / 4096.0
|
||||
|
||||
return int32(pValue * 1000), nil
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
d.waitForOneShot()
|
||||
|
||||
// read data
|
||||
data := []byte{0, 0}
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_TEMP_OUT_REG, data[:1])
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_TEMP_OUT_REG+1, data[1:])
|
||||
tValue := float32(int16(uint16(data[1])<<8|uint16(data[0]))) / 100.0
|
||||
|
||||
return int32(tValue * 1000), nil
|
||||
}
|
||||
|
||||
// private functions
|
||||
|
||||
// wait and trigger one shot in block update
|
||||
func (d *Device) waitForOneShot() {
|
||||
// trigger one shot
|
||||
d.bus.WriteRegister(d.Address, LPS22HB_CTRL2_REG, []byte{0x01})
|
||||
|
||||
// wait until one shot is cleared
|
||||
data := []byte{1}
|
||||
for {
|
||||
d.bus.ReadRegister(d.Address, LPS22HB_CTRL2_REG, data)
|
||||
if data[0]&0x01 == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
//go:build !nano_33_ble
|
||||
// +build !nano_33_ble
|
||||
|
||||
package lps22hb
|
||||
|
||||
import "tinygo.org/x/drivers"
|
||||
|
||||
// New creates a new LPS22HB 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: LPS22HB_ADDRESS}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
//go:build nano_33_ble
|
||||
// +build nano_33_ble
|
||||
|
||||
package lps22hb
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// New creates a new LPS22HB 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 {
|
||||
// turn on internal power pin (machine.P0_22) and I2C1 pullups power pin (machine.P1_00)
|
||||
// and wait a moment.
|
||||
ENV := machine.P0_22
|
||||
ENV.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
ENV.High()
|
||||
R := machine.P1_00
|
||||
R.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
R.High()
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
|
||||
return Device{bus: bus, Address: LPS22HB_ADDRESS}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package lps22hb
|
||||
|
||||
const (
|
||||
|
||||
// I2C address
|
||||
LPS22HB_ADDRESS = 0x5C
|
||||
|
||||
// control/status registers
|
||||
LPS22HB_WHO_AM_I_REG = 0x0F
|
||||
LPS22HB_CTRL1_REG = 0x10
|
||||
LPS22HB_CTRL2_REG = 0x11
|
||||
LPS22HB_STATUS_REG = 0x27
|
||||
LPS22HB_PRESS_OUT_REG = 0x28
|
||||
LPS22HB_TEMP_OUT_REG = 0x2B
|
||||
)
|
||||
@@ -191,14 +191,14 @@ func (d *Device) ReadCompass() (h int32) {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in Celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (c int32, e error) {
|
||||
func (d *Device) ReadTemperature() (c drivers.Temperature, e error) {
|
||||
|
||||
data1, data2 := []byte{0}, []byte{0}
|
||||
d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_H_A, data1)
|
||||
d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_L_A, data2)
|
||||
|
||||
t := int16((uint16(data1[0])<<8 | uint16(data2[0]))) >> 4 // temperature offsef from 25 °C
|
||||
c = int32((float32(25) + float32(t)/8) * 1000)
|
||||
c = drivers.Temperature(t)*125 + 25000
|
||||
e = nil
|
||||
return
|
||||
}
|
||||
|
||||
+2
-2
@@ -165,13 +165,13 @@ func (d *Device) ReadRotation() (x int32, y int32, z int32) {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (int32, error) {
|
||||
func (d *Device) ReadTemperature() (drivers.Temperature, error) {
|
||||
d.bus.ReadRegister(uint8(d.Address), OUT_TEMP_L, d.dataBufferTwo)
|
||||
|
||||
// From "Table 5. Temperature sensor characteristics"
|
||||
// temp = value/16 + 25
|
||||
t := 25000 + (int32(int16((int16(d.dataBufferTwo[1])<<8)|int16(d.dataBufferTwo[0])))*125)/2
|
||||
return t, nil
|
||||
return drivers.Temperature(t), nil
|
||||
}
|
||||
|
||||
// ReadSteps returns the steps of the pedometer
|
||||
|
||||
@@ -110,11 +110,11 @@ func (d *Device) ReadRotation() (x int32, y int32, z int32) {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (int32, error) {
|
||||
func (d *Device) ReadTemperature() (drivers.Temperature, error) {
|
||||
d.bus.ReadRegister(uint8(d.Address), OUT_TEMP_L, d.dataBufferTwo)
|
||||
|
||||
// From "Table 4. Temperature sensor characteristics"
|
||||
// temp = value/256 + 25
|
||||
t := 25000 + (int32(int16((int16(d.dataBufferTwo[1])<<8)|int16(d.dataBufferTwo[0])))*125)/32
|
||||
return t, nil
|
||||
return drivers.Temperature(t), nil
|
||||
}
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
// LSM9DS1, 9 axis Inertial Measurement Unit (IMU)
|
||||
//
|
||||
// Datasheet: https://www.st.com/resource/en/datasheet/lsm6ds3.pdf
|
||||
//
|
||||
package lsm9ds1 // import "tinygo.org/x/drivers/lsm9ds1"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
type AccelRange uint8
|
||||
type AccelSampleRate uint8
|
||||
type AccelBandwidth uint8
|
||||
|
||||
type GyroRange uint8
|
||||
type GyroSampleRate uint8
|
||||
|
||||
type MagRange uint8
|
||||
type MagSampleRate uint8
|
||||
|
||||
// Device wraps connection to a LSM9DS1 device.
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
AccelAddress uint8
|
||||
MagAddress uint8
|
||||
accelMultiplier int32
|
||||
gyroMultiplier int32
|
||||
magMultiplier int32
|
||||
dataBufferSix []uint8
|
||||
dataBufferTwo []uint8
|
||||
}
|
||||
|
||||
// Configuration for LSM9DS1 device.
|
||||
type Configuration struct {
|
||||
AccelRange AccelRange
|
||||
AccelSampleRate AccelSampleRate
|
||||
AccelBandWidth AccelBandwidth
|
||||
GyroRange GyroRange
|
||||
GyroSampleRate GyroSampleRate
|
||||
MagRange MagRange
|
||||
MagSampleRate MagSampleRate
|
||||
}
|
||||
|
||||
var errNotConnected = errors.New("lsm9ds1: failed to communicate with either acel/gyro or magnet sensor")
|
||||
|
||||
// New creates a new LSM9DS1 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,
|
||||
AccelAddress: ACCEL_ADDRESS,
|
||||
MagAddress: MAG_ADDRESS,
|
||||
dataBufferSix: make([]uint8, 6),
|
||||
dataBufferTwo: make([]uint8, 2),
|
||||
}
|
||||
}
|
||||
|
||||
// Connected returns whether both sensor on LSM9DS1 has been found.
|
||||
// It does two "who am I" requests and checks the responses.
|
||||
// In a rare case of an I2C bus issue, it can also return an error.
|
||||
// Case of boolean false and error nil means I2C is up,
|
||||
// but "who am I" responses have unexpected values.
|
||||
func (d *Device) Connected() (connected bool, err error) {
|
||||
data1, data2 := []byte{0}, []byte{0}
|
||||
err = d.bus.ReadRegister(d.AccelAddress, WHO_AM_I, data1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = d.bus.ReadRegister(d.MagAddress, WHO_AM_I_M, data2)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return data1[0] == 0x68 && data2[0] == 0x3D, nil
|
||||
}
|
||||
|
||||
// ReadAcceleration reads the current acceleration from the device and returns
|
||||
// it in µg (micro-gravity). When one of the axes is pointing straight to Earth
|
||||
// and the sensor is not moving the returned value will be around 1000000 or
|
||||
// -1000000.
|
||||
func (d *Device) ReadAcceleration() (x, y, z int32, err error) {
|
||||
err = d.bus.ReadRegister(uint8(d.AccelAddress), OUT_X_L_XL, d.dataBufferSix)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
x = int32(int16((uint16(d.dataBufferSix[1])<<8)|uint16(d.dataBufferSix[0]))) * d.accelMultiplier
|
||||
y = int32(int16((uint16(d.dataBufferSix[3])<<8)|uint16(d.dataBufferSix[2]))) * d.accelMultiplier
|
||||
z = int32(int16((uint16(d.dataBufferSix[5])<<8)|uint16(d.dataBufferSix[4]))) * d.accelMultiplier
|
||||
return
|
||||
}
|
||||
|
||||
// ReadRotation reads the current rotation from the device and returns it in
|
||||
// µ°/s (micro-degrees/sec). This means that if you were to do a complete
|
||||
// rotation along one axis and while doing so integrate all values over time,
|
||||
// you would get a value close to 360000000.
|
||||
func (d *Device) ReadRotation() (x, y, z int32, err error) {
|
||||
err = d.bus.ReadRegister(uint8(d.AccelAddress), OUT_X_L_G, d.dataBufferSix)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
x = int32(int16((uint16(d.dataBufferSix[1])<<8)|uint16(d.dataBufferSix[0]))) * d.gyroMultiplier
|
||||
y = int32(int16((uint16(d.dataBufferSix[3])<<8)|uint16(d.dataBufferSix[2]))) * d.gyroMultiplier
|
||||
z = int32(int16((uint16(d.dataBufferSix[5])<<8)|uint16(d.dataBufferSix[4]))) * d.gyroMultiplier
|
||||
return
|
||||
}
|
||||
|
||||
// ReadMagneticField reads the current magnetic field from the device and returns
|
||||
// it in nT (nanotesla). 1 G (gauss) = 100_000 nT (nanotesla).
|
||||
func (d *Device) ReadMagneticField() (x, y, z int32, err error) {
|
||||
err = d.bus.ReadRegister(uint8(d.MagAddress), OUT_X_L_M, d.dataBufferSix)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
x = int32(int16((int16(d.dataBufferSix[1])<<8)|int16(d.dataBufferSix[0]))) * d.magMultiplier
|
||||
y = int32(int16((int16(d.dataBufferSix[3])<<8)|int16(d.dataBufferSix[2]))) * d.magMultiplier
|
||||
z = int32(int16((int16(d.dataBufferSix[5])<<8)|int16(d.dataBufferSix[4]))) * d.magMultiplier
|
||||
return
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in Celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (t int32, err error) {
|
||||
err = d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_L, d.dataBufferTwo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// From "Table 5. Temperature sensor characteristics"
|
||||
// temp = value/16 + 25
|
||||
t = 25000 + (int32(int16((int16(d.dataBufferTwo[1])<<8)|int16(d.dataBufferTwo[0])))*125)/2
|
||||
return
|
||||
}
|
||||
|
||||
// --- end of public methods --------------------------------------------------
|
||||
|
||||
// doConfigure is called by public Configure methods after all
|
||||
// necessary board-specific initialisations are taken care of
|
||||
func (d *Device) doConfigure(cfg Configuration) (err error) {
|
||||
|
||||
// Verify unit communication
|
||||
if con, err := d.Connected(); !con || err != nil {
|
||||
return errNotConnected
|
||||
}
|
||||
|
||||
// Multipliers come from "Table 3. Sensor characteristics" of the datasheet * 1000
|
||||
switch cfg.AccelRange {
|
||||
case ACCEL_2G:
|
||||
d.accelMultiplier = 61
|
||||
case ACCEL_4G:
|
||||
d.accelMultiplier = 122
|
||||
case ACCEL_8G:
|
||||
d.accelMultiplier = 244
|
||||
case ACCEL_16G:
|
||||
d.accelMultiplier = 732
|
||||
}
|
||||
switch cfg.GyroRange {
|
||||
case GYRO_250DPS:
|
||||
d.gyroMultiplier = 8750
|
||||
case GYRO_500DPS:
|
||||
d.gyroMultiplier = 17500
|
||||
case GYRO_2000DPS:
|
||||
d.gyroMultiplier = 70000
|
||||
}
|
||||
switch cfg.MagRange {
|
||||
case MAG_4G:
|
||||
d.magMultiplier = 14
|
||||
case MAG_8G:
|
||||
d.magMultiplier = 29
|
||||
case MAG_12G:
|
||||
d.magMultiplier = 43
|
||||
case MAG_16G:
|
||||
d.magMultiplier = 58
|
||||
}
|
||||
|
||||
data := make([]byte, 1)
|
||||
|
||||
// Configure accelerometer
|
||||
// Sample rate & measurement range
|
||||
data[0] = uint8(cfg.AccelSampleRate)<<5 | uint8(cfg.AccelRange)<<3
|
||||
err = d.bus.WriteRegister(d.AccelAddress, CTRL_REG6_XL, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Configure gyroscope
|
||||
// Sample rate & measurement range
|
||||
data[0] = uint8(cfg.GyroSampleRate)<<5 | uint8(cfg.GyroRange)<<3
|
||||
err = d.bus.WriteRegister(d.AccelAddress, CTRL_REG1_G, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Configure magnetometer
|
||||
|
||||
// Temperature compensation enabled
|
||||
// High-performance mode XY axis
|
||||
// Sample rate
|
||||
data[0] = 0b10000000 | 0b01000000 | uint8(cfg.MagSampleRate)<<2
|
||||
err = d.bus.WriteRegister(d.MagAddress, CTRL_REG1_M, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Measurement range
|
||||
data[0] = uint8(cfg.MagRange) << 5
|
||||
err = d.bus.WriteRegister(d.MagAddress, CTRL_REG2_M, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Continuous-conversion mode
|
||||
// https://electronics.stackexchange.com/questions/237397/continuous-conversion-vs-single-conversion-mode
|
||||
data[0] = 0b00000000
|
||||
err = d.bus.WriteRegister(d.MagAddress, CTRL_REG3_M, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// High-performance mode Z axis
|
||||
data[0] = 0b00001000
|
||||
err = d.bus.WriteRegister(d.MagAddress, CTRL_REG4_M, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
//go:build !nano_33_ble
|
||||
// +build !nano_33_ble
|
||||
|
||||
package lsm9ds1
|
||||
|
||||
// Configure sets up the device for communication.
|
||||
func (d *Device) Configure(cfg Configuration) error {
|
||||
return d.doConfigure(cfg)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
//go:build nano_33_ble
|
||||
// +build nano_33_ble
|
||||
|
||||
// Nano 33 BLE [Sense] has LSM9DS1 unit on-board.
|
||||
// This custom Configure function powers unit up
|
||||
// and enables I2C, so unit can can be accessed.
|
||||
package lsm9ds1
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Configure sets up the device for communication.
|
||||
func (d *Device) Configure(cfg Configuration) error {
|
||||
// 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)
|
||||
// Common initialisation code
|
||||
return d.doConfigure(cfg)
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package lsm9ds1
|
||||
|
||||
// Constants/addresses used for I2C.
|
||||
|
||||
const (
|
||||
|
||||
// Constants/addresses used for I2C.
|
||||
ACCEL_ADDRESS = 0x6B
|
||||
MAG_ADDRESS = 0x1E
|
||||
|
||||
// Table 21. Accelerometer and gyroscope register address map
|
||||
WHO_AM_I = 0x0F // value 0x68
|
||||
CTRL_REG1_G = 0x10
|
||||
OUT_X_L_G = 0x18
|
||||
OUT_X_H_G = 0x19
|
||||
OUT_Y_L_G = 0x1A
|
||||
OUT_Y_H_G = 0x1B
|
||||
OUT_Z_L_G = 0x1C
|
||||
OUT_Z_H_G = 0x1D
|
||||
OUT_TEMP_L = 0x15
|
||||
OUT_TEMP_H = 0x16
|
||||
CTRL_REG6_XL = 0x20
|
||||
STATUS_REG = 0x27
|
||||
OUT_X_L_XL = 0x28
|
||||
OUT_X_H_XL = 0x29
|
||||
OUT_Y_L_XL = 0x2A
|
||||
OUT_Y_H_XL = 0x2B
|
||||
OUT_Z_L_XL = 0x2C
|
||||
OUT_Z_H_XL = 0x2D
|
||||
|
||||
// Table 22. Magnetic sensor register address map
|
||||
OFFSET_X_REG_L_M = 0x05
|
||||
OFFSET_X_REG_H_M = 0x06
|
||||
OFFSET_Y_REG_L_M = 0x07
|
||||
OFFSET_Y_REG_H_M = 0x08
|
||||
OFFSET_Z_REG_L_M = 0x09
|
||||
OFFSET_Z_REG_H_M = 0x0A
|
||||
WHO_AM_I_M = 0x0F // value 0x3D
|
||||
CTRL_REG1_M = 0x20 // TEMP_COMP OM1 OM0 DO2 DO1 DO0 FAST_ODR ST
|
||||
CTRL_REG2_M = 0x21 // 0 FS1 FS0 0 REBOOT SOFT_RST 0 0
|
||||
CTRL_REG3_M = 0x22 // 0 LP 0 0 SIM MD1 MD0
|
||||
CTRL_REG4_M = 0x23 // 0 0 0 0 OMZ1 OMZ0 BLE 0
|
||||
STATUS_REG_M = 0x27
|
||||
OUT_X_L_M = 0x28
|
||||
OUT_X_H_M = 0x29
|
||||
OUT_Y_L_M = 0x2A
|
||||
OUT_Y_H_M = 0x2B
|
||||
OUT_Z_L_M = 0x2C
|
||||
OUT_Z_H_M = 0x2D
|
||||
|
||||
// Table 67. CTRL_REG6_XL register description
|
||||
ACCEL_2G AccelRange = 0b00
|
||||
ACCEL_4G AccelRange = 0b10
|
||||
ACCEL_8G AccelRange = 0b11
|
||||
ACCEL_16G AccelRange = 0b01
|
||||
|
||||
// Table 68. ODR register setting (accelerometer only mode)
|
||||
ACCEL_SR_OFF AccelSampleRate = 0b000
|
||||
ACCEL_SR_10 AccelSampleRate = 0b001
|
||||
ACCEL_SR_50 AccelSampleRate = 0b010
|
||||
ACCEL_SR_119 AccelSampleRate = 0b011
|
||||
ACCEL_SR_238 AccelSampleRate = 0b100
|
||||
ACCEL_SR_476 AccelSampleRate = 0b101
|
||||
ACCEL_SR_952 AccelSampleRate = 0b110
|
||||
|
||||
// Table 67. CTRL_REG6_XL register description
|
||||
ACCEL_BW_50 AccelBandwidth = 0b11
|
||||
ACCEL_BW_105 AccelBandwidth = 0b10
|
||||
ACCEL_BW_211 AccelBandwidth = 0b01
|
||||
ACCEL_BW_408 AccelBandwidth = 0b00
|
||||
|
||||
// Table 45. CTRL_REG1_G register description
|
||||
GYRO_250DPS GyroRange = 0b00
|
||||
GYRO_500DPS GyroRange = 0b01
|
||||
GYRO_2000DPS GyroRange = 0b11
|
||||
|
||||
// Table 9. Gyroscope operating modes
|
||||
// Table 46. ODR and BW configuration setting (after LPF1)
|
||||
GYRO_SR_OFF GyroSampleRate = 0b000
|
||||
GYRO_SR_15 GyroSampleRate = 0b001
|
||||
GYRO_SR_60 GyroSampleRate = 0b010
|
||||
GYRO_SR_119 GyroSampleRate = 0b011
|
||||
GYRO_SR_238 GyroSampleRate = 0b100
|
||||
GYRO_SR_476 GyroSampleRate = 0b101
|
||||
GYRO_SR_952 GyroSampleRate = 0b110
|
||||
|
||||
// Table 114. Full-scale selection
|
||||
MAG_4G MagRange = 0b00
|
||||
MAG_8G MagRange = 0b01
|
||||
MAG_12G MagRange = 0b10
|
||||
MAG_16G MagRange = 0b11
|
||||
|
||||
// Table 111. Output data rate configuration
|
||||
MAG_SR_06 MagSampleRate = 0b000
|
||||
MAG_SR_1 MagSampleRate = 0b001
|
||||
MAG_SR_2 MagSampleRate = 0b010
|
||||
MAG_SR_5 MagSampleRate = 0b011
|
||||
MAG_SR_10 MagSampleRate = 0b100
|
||||
MAG_SR_20 MagSampleRate = 0b101
|
||||
MAG_SR_40 MagSampleRate = 0b110
|
||||
MAG_SR_80 MagSampleRate = 0b111
|
||||
)
|
||||
+2
-2
@@ -49,8 +49,8 @@ func (d Device) ReadMagnetic() (x int16, y int16, z int16) {
|
||||
|
||||
// ReadTemperature reads and returns the current die temperature in
|
||||
// celsius milli degrees (°C/1000).
|
||||
func (d Device) ReadTemperature() (int32, error) {
|
||||
func (d Device) ReadTemperature() (drivers.Temperature, error) {
|
||||
data := make([]byte, 1)
|
||||
d.bus.ReadRegister(uint8(d.Address), DIE_TEMP, data)
|
||||
return int32(data[0]) * 1000, nil
|
||||
return drivers.Temperature(data[0]) * 1000, nil
|
||||
}
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ func (p ADCPin) Get() uint16 {
|
||||
p.d.bus.Tx(p.d.tx, p.d.rx)
|
||||
|
||||
// scale result to 16bit value like other ADCs
|
||||
result := uint16((p.d.rx[1]&0x3))<<(8+6) + uint16(p.d.rx[2])<<6
|
||||
result := uint16((p.d.rx[1]&0x3))<<8 + uint16(p.d.rx[2])<<6
|
||||
p.d.cs.High()
|
||||
|
||||
return result
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ func (c *TCPSerialConn) LocalAddr() Addr {
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
func (c *TCPSerialConn) RemoteAddr() Addr {
|
||||
return c.raddr.opAddr()
|
||||
return c.laddr.opAddr()
|
||||
}
|
||||
|
||||
func (c *TCPSerialConn) opConn() Conn {
|
||||
|
||||
+6
-6
@@ -2,7 +2,7 @@
|
||||
// series by Sensirion.
|
||||
//
|
||||
// Datasheet:
|
||||
// https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf
|
||||
// https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf
|
||||
//
|
||||
package sht3x // import "tinygo.org/x/drivers/sht3x"
|
||||
|
||||
@@ -31,9 +31,9 @@ func New(bus drivers.I2C) Device {
|
||||
}
|
||||
|
||||
// Read returns the temperature in celsius milli degrees (°C/1000).
|
||||
func (d *Device) ReadTemperature() (tempMilliCelsius int32, err error) {
|
||||
func (d *Device) ReadTemperature() (tempMilliCelsius drivers.Temperature, err error) {
|
||||
tempMilliCelsius, _, err = d.ReadTemperatureHumidity()
|
||||
return tempMilliCelsius, err
|
||||
return drivers.Temperature(tempMilliCelsius), err
|
||||
}
|
||||
|
||||
// Read returns the relative humidity in hundredths of a percent.
|
||||
@@ -43,15 +43,15 @@ func (d *Device) ReadHumidity() (relativeHumidity int16, err error) {
|
||||
}
|
||||
|
||||
// Read returns both the temperature and relative humidity.
|
||||
func (d *Device) ReadTemperatureHumidity() (tempMilliCelsius int32, relativeHumidity int16, err error) {
|
||||
func (d *Device) ReadTemperatureHumidity() (tempMilliCelsius drivers.Temperature, relativeHumidity int16, err error) {
|
||||
var rawTemp, rawHum, errx = d.rawReadings()
|
||||
if errx != nil {
|
||||
err = errx
|
||||
return
|
||||
}
|
||||
tempMilliCelsius = (35000 * int32(rawTemp) / 13107) - 45000
|
||||
tempMilliCelsius = drivers.Temperature((35000 * int32(rawTemp) / 13107) - 45000)
|
||||
relativeHumidity = int16(2000 * int32(rawHum) / 13107)
|
||||
return tempMilliCelsius, relativeHumidity, err
|
||||
return
|
||||
}
|
||||
|
||||
// rawReadings returns the sensor's raw values of the temperature and humidity
|
||||
|
||||
@@ -29,6 +29,8 @@ package thermistor // import "tinygo.org/x/drivers/thermistor"
|
||||
import (
|
||||
"machine"
|
||||
"math"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device holds the ADC pin and the needed settings for calculating the
|
||||
@@ -61,7 +63,7 @@ func (d *Device) Configure() {
|
||||
}
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) {
|
||||
var reading uint32
|
||||
if d.HighSide {
|
||||
// Thermistor connected from analog input to high logic level.
|
||||
@@ -82,5 +84,5 @@ func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
steinhart = 1.0 / steinhart // Invert
|
||||
steinhart -= 273.15 // convert to C
|
||||
|
||||
return int32(steinhart * 1000), nil
|
||||
return drivers.Temperature(steinhart * 1000), nil
|
||||
}
|
||||
|
||||
+3
-3
@@ -46,7 +46,7 @@ func (d *Device) Connected() bool {
|
||||
}
|
||||
|
||||
// Reads the temperature from the sensor and returns it in celsius milli degrees (°C/1000).
|
||||
func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) {
|
||||
|
||||
tmpData := make([]byte, 2)
|
||||
|
||||
@@ -62,7 +62,7 @@ func (d *Device) ReadTemperature() (temperature int32, err error) {
|
||||
temperatureSum |= int32(0xf800)
|
||||
}
|
||||
|
||||
temperature = temperatureSum * 625
|
||||
temperature = drivers.Temperature(temperatureSum * 625 / 10)
|
||||
|
||||
return temperature / 10, nil
|
||||
return temperature, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package drivers
|
||||
|
||||
// This file contains some common units that can be used in a sensor driver.
|
||||
|
||||
// Temperature is a temperature in Celsius milli degrees (°C/1000). For example,
|
||||
// the value 25000 is 25°C.
|
||||
type Temperature int32
|
||||
|
||||
// Celsius returns the temperature in degrees Celsius.
|
||||
func (t Temperature) Celsius() float32 {
|
||||
return float32(t) / 1000
|
||||
}
|
||||
|
||||
// Fahrenheit returns the temperature in degrees Fahrenheit.
|
||||
func (t Temperature) Fahrenheit() float32 {
|
||||
return t.Celsius()*1.8 + 32
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package drivers
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTemperature(t *testing.T) {
|
||||
tests := []struct {
|
||||
t Temperature
|
||||
c float32 // Celsius
|
||||
f float32 // Fahrenheit
|
||||
}{
|
||||
{-40000, -40, -40}, // -40°C
|
||||
{0, 0, 32}, // 0°C
|
||||
{20000, 20, 68}, // 20°C
|
||||
{25000, 25, 77}, // 25°C
|
||||
}
|
||||
for _, tc := range tests {
|
||||
c := tc.t.Celsius()
|
||||
f := tc.t.Fahrenheit()
|
||||
if c != tc.c {
|
||||
t.Errorf("expected value %d to be %f°C, but got %f°C", tc.t, tc.c, c)
|
||||
}
|
||||
if f != tc.f {
|
||||
t.Errorf("expected value %d to be %f°F, but got %f°F", tc.t, tc.f, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,4 +2,4 @@ package drivers
|
||||
|
||||
// Version returns a user-readable string showing the version of the drivers package for support purposes.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.18.0"
|
||||
const Version = "0.17.1"
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
package wifinina
|
||||
|
||||
import "errors"
|
||||
|
||||
// Mimics machine package's pin control
|
||||
//
|
||||
// NB! These are NINA chip pins, not main unit pins.
|
||||
//
|
||||
// Digital pin values and modes taken from
|
||||
// https://github.com/arduino/nina-fw/blob/master/arduino/cores/esp32/wiring_digital.h
|
||||
|
||||
type Pin uint8
|
||||
|
||||
const (
|
||||
PinLow uint8 = iota
|
||||
PinHigh
|
||||
)
|
||||
|
||||
type PinMode uint8
|
||||
|
||||
const (
|
||||
PinInput PinMode = iota
|
||||
PinOutput
|
||||
PinInputPullup
|
||||
)
|
||||
|
||||
type PinConfig struct {
|
||||
Mode PinMode
|
||||
}
|
||||
|
||||
var (
|
||||
ErrPinNoDevice = errors.New("wifinina pin: device not set")
|
||||
)
|
||||
|
||||
var pinDevice *Device
|
||||
|
||||
func pinUseDevice(d *Device) {
|
||||
pinDevice = d
|
||||
}
|
||||
|
||||
func (p Pin) Configure(config PinConfig) error {
|
||||
if pinDevice == nil {
|
||||
return ErrPinNoDevice
|
||||
}
|
||||
return pinDevice.PinMode(uint8(p), uint8(config.Mode))
|
||||
}
|
||||
|
||||
func (p Pin) Set(high bool) error {
|
||||
if pinDevice == nil {
|
||||
return ErrPinNoDevice
|
||||
}
|
||||
value := PinLow
|
||||
if high {
|
||||
value = PinHigh
|
||||
}
|
||||
return pinDevice.DigitalWrite(uint8(p), value)
|
||||
}
|
||||
|
||||
func (p Pin) High() error {
|
||||
return p.Set(true)
|
||||
}
|
||||
|
||||
func (p Pin) Low() error {
|
||||
return p.Set(false)
|
||||
}
|
||||
@@ -297,7 +297,6 @@ func New(bus drivers.SPI, csPin, ackPin, gpio0Pin, resetPin machine.Pin) *Device
|
||||
func (d *Device) Configure() {
|
||||
|
||||
net.UseDriver(d.NewDriver())
|
||||
pinUseDevice(d)
|
||||
|
||||
d.CS.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
d.ACK.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||
@@ -690,23 +689,6 @@ func (d *Device) StartScanNetworks() (uint8, error) {
|
||||
return d.getUint8(d.req0(CmdStartScanNetworks))
|
||||
}
|
||||
|
||||
func (d *Device) PinMode(pin uint8, mode uint8) error {
|
||||
_, err := d.req2Uint8(CmdSetPinMode, pin, mode)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Device) DigitalWrite(pin uint8, value uint8) error {
|
||||
_, err := d.req2Uint8(CmdSetDigitalWrite, pin, value)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Device) AnalogWrite(pin uint8, value uint8) error {
|
||||
_, err := d.req2Uint8(CmdSetAnalogWrite, pin, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// ------------- End of public device interface ----------------------------
|
||||
|
||||
func (d *Device) getString(l uint8, err error) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -791,14 +773,6 @@ func (d *Device) reqUint8(cmd uint8, data uint8) (l uint8, err error) {
|
||||
return d.waitRspCmd1(cmd)
|
||||
}
|
||||
|
||||
// req2Uint8 sends a command to the device with two uint8 parameters
|
||||
func (d *Device) req2Uint8(cmd, p1, p2 uint8) (l uint8, err error) {
|
||||
if err := d.sendCmdPadded2(cmd, p1, p2); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.waitRspCmd1(cmd)
|
||||
}
|
||||
|
||||
// reqStr sends a command to the device with a single string parameter
|
||||
func (d *Device) reqStr(cmd uint8, p1 string) (uint8, error) {
|
||||
if err := d.sendCmdStr(cmd, p1); err != nil {
|
||||
@@ -860,18 +834,6 @@ func (d *Device) sendCmdPadded1(cmd uint8, data uint8) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Device) sendCmdPadded2(cmd, data1, data2 uint8) error {
|
||||
defer d.spiChipDeselect()
|
||||
if err := d.waitForChipSelect(); err != nil {
|
||||
return err
|
||||
}
|
||||
l := d.sendCmd(cmd, 1)
|
||||
l += d.sendParam8(data1, false)
|
||||
l += d.sendParam8(data2, true)
|
||||
d.SPI.Transfer(dummyData)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Device) sendCmdStr(cmd uint8, p1 string) (err error) {
|
||||
defer d.spiChipDeselect()
|
||||
if err := d.waitForChipSelect(); err != nil {
|
||||
|
||||
@@ -5,11 +5,9 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -36,77 +34,10 @@ import (
|
||||
// The timings deviate a little bit from the code here, but so far the timings
|
||||
// from wp.josh.com seem to be fine for the ws2812.
|
||||
|
||||
// Architecture implementation. Describes the template and the timings of the
|
||||
// blocks of instructions so that most code can remain architecture-independent.
|
||||
type architectureImpl struct {
|
||||
buildTag string
|
||||
minBaseCyclesT0H int
|
||||
maxBaseCyclesT0H int
|
||||
minBaseCyclesT1H int
|
||||
maxBaseCyclesT1H int
|
||||
minBaseCyclesTLD int
|
||||
valueTemplate string // template for how to pass the 'c' byte to assembly
|
||||
template string // assembly template
|
||||
}
|
||||
// Clock frequencies to support, in MHz.
|
||||
var clockFrequencies = []int{16, 48, 64, 120, 168}
|
||||
|
||||
var architectures = map[string]architectureImpl{
|
||||
"cortexm": {
|
||||
// Assume that a branch is 1 to 3 cycles, no matter whether it's taken
|
||||
// or not. This is a rather conservative estimate, for Cortex-M+ for
|
||||
// example the instruction cycles are precisely known.
|
||||
buildTag: "cortexm",
|
||||
minBaseCyclesT0H: 1 + 1 + 2, // shift + branch (not taken) + store
|
||||
maxBaseCyclesT0H: 1 + 3 + 2, // shift + branch (not taken) + store
|
||||
minBaseCyclesT1H: 1 + 1 + 2, // shift + branch (taken) + store
|
||||
maxBaseCyclesT1H: 1 + 3 + 2, // shift + branch (taken) + store
|
||||
minBaseCyclesTLD: 1 + 1 + 2, // subtraction + branch + store (in next cycle)
|
||||
valueTemplate: "uint32(c) << 24",
|
||||
template: `
|
||||
1: @ send_bit
|
||||
str {maskSet}, {portSet} @ [2] T0H and T0L start here
|
||||
@DELAY1
|
||||
lsls {value}, #1 @ [1]
|
||||
bcs.n 2f @ [1/3] skip_store
|
||||
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
|
||||
2: @ skip_store
|
||||
@DELAY2
|
||||
str {maskClear}, {portClear} @ [2] T1H -> T1L transition
|
||||
@DELAY3
|
||||
subs {i}, #1 @ [1]
|
||||
bne.n 1b @ [1/3] send_bit
|
||||
`,
|
||||
},
|
||||
"tinygoriscv": {
|
||||
// Largely based on the SiFive FE310 CPU:
|
||||
// - stores are 1 cycle
|
||||
// - branches are 1 or 3 cycles, depending on branch prediction
|
||||
// - ALU operations are 1 cycle (as on most CPUs)
|
||||
// Hopefully this generalizes to other chips.
|
||||
buildTag: "tinygo.riscv32",
|
||||
minBaseCyclesT0H: 1 + 1 + 1, // shift + branch (not taken) + store
|
||||
maxBaseCyclesT0H: 1 + 3 + 1, // shift + branch (not taken) + store
|
||||
minBaseCyclesT1H: 1 + 1 + 1, // shift + branch (taken) + store
|
||||
maxBaseCyclesT1H: 1 + 3 + 1, // shift + branch (taken) + store
|
||||
minBaseCyclesTLD: 1 + 1 + 1, // subtraction + branch + store (in next cycle)
|
||||
valueTemplate: "uint32(c) << 23",
|
||||
template: `
|
||||
1: // send_bit
|
||||
sw {maskSet}, {portSet} // [1] T0H and T0L start here
|
||||
@DELAY1
|
||||
slli {value}, {value}, 1 // [1] shift value left by 1
|
||||
bltz {value}, 2f // [1/3] skip_store
|
||||
sw {maskClear}, {portClear} // [1] T0H -> T0L transition
|
||||
2: // skip_store
|
||||
@DELAY2
|
||||
sw {maskClear}, {portClear} // [1] T1H -> T1L transition
|
||||
@DELAY3
|
||||
addi {i}, {i}, -1 // [1]
|
||||
bnez {i}, 1b // [1/3] send_bit
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
func writeImplementation(f *os.File, arch string, megahertz int) error {
|
||||
func writeImplementation(f *os.File, megahertz int) error {
|
||||
cycleTimeNS := 1 / float64(megahertz)
|
||||
// These timings are taken from the table "Updated simplified timing
|
||||
// constraints for NeoPixel strings" at:
|
||||
@@ -141,7 +72,7 @@ func writeImplementation(f *os.File, arch string, megahertz int) error {
|
||||
maxCyclesT1H := int(math.Floor(5.500 / cycleTimeNS))
|
||||
minCyclesTLD := int(math.Ceil(1.150 / cycleTimeNS))
|
||||
|
||||
// The assembly template looks something like this:
|
||||
// Assembly template:
|
||||
// 1: @ send_bit
|
||||
// str {maskSet}, {portSet} @ [2] T0H and T0L start here
|
||||
// ...delay 1
|
||||
@@ -156,31 +87,29 @@ func writeImplementation(f *os.File, arch string, megahertz int) error {
|
||||
// bne.n 1b @ [1/3] send_bit
|
||||
//
|
||||
// We need to calculate the number of nop instructions in the three delays.
|
||||
archImpl, ok := architectures[arch]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown architecture: %s", arch)
|
||||
}
|
||||
|
||||
// Determine number of nops for delay1. This is primarily based on the T0H
|
||||
// delay, which is relatively short (<500ns).
|
||||
delay1 := minCyclesT0H - archImpl.minBaseCyclesT0H
|
||||
minBaseCyclesT0H := 1 + 1 + 2 // shift + branch + store
|
||||
maxBaseCyclesT0H := 1 + 3 + 2 // shift + branch + store
|
||||
delay1 := minCyclesT0H - minBaseCyclesT0H
|
||||
if delay1 < 0 {
|
||||
// The minCyclesT0H constraint could not be satisfied. Don't insert
|
||||
// nops, in the hope that it isn't too long.
|
||||
delay1 = 0
|
||||
}
|
||||
if delay1+archImpl.maxBaseCyclesT0H > maxCyclesT0H {
|
||||
if delay1+maxBaseCyclesT0H > maxCyclesT0H {
|
||||
return fmt.Errorf("MCU appears to be too slow to satisfy minimum requirements for the T0H signal")
|
||||
}
|
||||
actualMinCyclesT0H := archImpl.minBaseCyclesT0H + delay1
|
||||
actualMaxCyclesT0H := archImpl.maxBaseCyclesT0H + delay1
|
||||
actualMinCyclesT0H := minBaseCyclesT0H + delay1
|
||||
actualMaxCyclesT0H := maxBaseCyclesT0H + delay1
|
||||
actualMinNanosecondsT0H := float64(actualMinCyclesT0H) / float64(megahertz) * 1000
|
||||
actualMaxNanosecondsT0H := float64(actualMaxCyclesT0H) / float64(megahertz) * 1000
|
||||
|
||||
// Determine number of nops for delay2. This is delay1 plus some extra time
|
||||
// so that the pulse is long enough for T1H.
|
||||
minBaseCyclesT1H := delay1 + archImpl.minBaseCyclesT1H // delay1 + asssembly cycles
|
||||
maxBaseCyclesT1H := delay1 + archImpl.maxBaseCyclesT1H // delay1 + asssembly cycles
|
||||
minBaseCyclesT1H := delay1 + 1 + 1 + 2 // delay1 + shift + branch + store
|
||||
maxBaseCyclesT1H := delay1 + 1 + 3 + 2 // delay1 + shift + branch + store
|
||||
delay2 := minCyclesT1H - minBaseCyclesT1H
|
||||
if delay2 < 0 {
|
||||
delay2 = 0
|
||||
@@ -196,11 +125,12 @@ func writeImplementation(f *os.File, arch string, megahertz int) error {
|
||||
|
||||
// Determine number of nops for delay3. This is based on the TLD delay, the
|
||||
// time between two high pulses.
|
||||
delay3 := minCyclesTLD - archImpl.minBaseCyclesTLD
|
||||
minBaseCyclesTLD := 1 + 1 + 2 // subtraction + branch + store (in next cycle)
|
||||
delay3 := minCyclesTLD - minBaseCyclesTLD
|
||||
if delay3 < 0 {
|
||||
delay3 = 0
|
||||
}
|
||||
actualMinCyclesTLD := archImpl.minBaseCyclesTLD + delay3
|
||||
actualMinCyclesTLD := minBaseCyclesTLD + delay3
|
||||
actualMinNanosecondsTLD := float64(actualMinCyclesTLD) / float64(megahertz) * 1000
|
||||
|
||||
// Create the Go function in a buffer. Using a buffer here to be able to
|
||||
@@ -216,13 +146,21 @@ func writeImplementation(f *os.File, arch string, megahertz int) error {
|
||||
fmt.Fprintf(buf, " // T1H: %2d - %2d cycles or %.1fns - %.1fns\n", actualMinCyclesT1H, actualMaxCyclesT1H, actualMinNanosecondsT1H, actualMaxNanosecondsT1H)
|
||||
fmt.Fprintf(buf, " // TLD: %2d - cycles or %.1fns -\n", actualMinCyclesTLD, actualMinNanosecondsTLD)
|
||||
fmt.Fprintf(buf, " mask := interrupt.Disable()\n")
|
||||
fmt.Fprintf(buf, " value := %s\n", archImpl.valueTemplate)
|
||||
asm := archImpl.template
|
||||
asm = strings.ReplaceAll(asm, " @DELAY1\n", strings.Repeat(" nop\n", delay1))
|
||||
asm = strings.ReplaceAll(asm, " @DELAY2\n", strings.Repeat(" nop\n", delay2))
|
||||
asm = strings.ReplaceAll(asm, " @DELAY3\n", strings.Repeat(" nop\n", delay3))
|
||||
asm = strings.ReplaceAll(asm, "\n", "\n\t")
|
||||
fmt.Fprintf(buf, " device.AsmFull(`%s`, map[string]interface{}{", asm)
|
||||
fmt.Fprintf(buf, " value := uint32(c) << 24\n")
|
||||
fmt.Fprintf(buf, " device.AsmFull(`\n")
|
||||
fmt.Fprintf(buf, " 1: @ send_bit\n")
|
||||
fmt.Fprintf(buf, " str {maskSet}, {portSet} @ [2] T0H and T0L start here\n")
|
||||
buf.WriteString(strings.Repeat(" nop\n", delay1))
|
||||
fmt.Fprintf(buf, " lsls {value}, #1 @ [1]\n")
|
||||
fmt.Fprintf(buf, " bcs.n 2f @ [1/3] skip_store\n")
|
||||
fmt.Fprintf(buf, " str {maskClear}, {portClear} @ [2] T0H -> T0L transition\n")
|
||||
fmt.Fprintf(buf, " 2: @ skip_store\n")
|
||||
buf.WriteString(strings.Repeat(" nop\n", delay2))
|
||||
fmt.Fprintf(buf, " str {maskClear}, {portClear} @ [2] T1H -> T1L transition\n")
|
||||
buf.WriteString(strings.Repeat(" nop\n", delay3))
|
||||
fmt.Fprintf(buf, " subs {i}, #1 @ [1]\n")
|
||||
fmt.Fprintf(buf, " bne.n 1b @ [1/3] send_bit\n")
|
||||
fmt.Fprintf(buf, " `, map[string]interface{}{")
|
||||
buf.WriteString(`
|
||||
"value": value,
|
||||
"i": 8,
|
||||
@@ -241,33 +179,19 @@ func writeImplementation(f *os.File, arch string, megahertz int) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
arch := flag.String("arch", "cortexm", "architecture to output to")
|
||||
flag.Parse()
|
||||
|
||||
// Remaining parameters are all clock frequencies.
|
||||
var clockFrequencies []int
|
||||
for _, s := range flag.Args() {
|
||||
freq, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "cannot parse frequency:", s)
|
||||
os.Exit(1)
|
||||
}
|
||||
clockFrequencies = append(clockFrequencies, freq)
|
||||
}
|
||||
|
||||
f, err := os.Create("ws2812-asm_" + *arch + ".go")
|
||||
f, err := os.Create("ws2812-asm_cortexm.go")
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "could not generate WS2812 assembly code:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
fmt.Fprintln(f, "//go:build", architectures[*arch].buildTag)
|
||||
fmt.Fprintln(f, "// +build", architectures[*arch].buildTag)
|
||||
f.WriteString(`
|
||||
f.WriteString(`//go:build cortexm
|
||||
// +build cortexm
|
||||
|
||||
package ws2812
|
||||
|
||||
// Warning: autogenerated file. Instead of modifying this file, change
|
||||
// gen-ws2812.go and run "go generate".
|
||||
// gen-ws2812-arm.go and run "go generate".
|
||||
|
||||
import (
|
||||
"device"
|
||||
@@ -275,9 +199,9 @@ import (
|
||||
)
|
||||
`)
|
||||
for _, megahertz := range clockFrequencies {
|
||||
err := writeImplementation(f, *arch, megahertz)
|
||||
err := writeImplementation(f, megahertz)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "could not generate WS2812 assembly code for %s and %dMHz: %s\n", *arch, megahertz, err)
|
||||
fmt.Fprintf(os.Stderr, "could not generate WS2812 assembly code for %dMHz: %s\n", megahertz, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
package ws2812
|
||||
|
||||
// Warning: autogenerated file. Instead of modifying this file, change
|
||||
// gen-ws2812.go and run "go generate".
|
||||
// gen-ws2812-arm.go and run "go generate".
|
||||
|
||||
import (
|
||||
"device"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -1,8 +1,7 @@
|
||||
// Package ws2812 implements a driver for WS2812 and SK6812 RGB LED strips.
|
||||
package ws2812 // import "tinygo.org/x/drivers/ws2812"
|
||||
|
||||
//go:generate go run gen-ws2812.go -arch=cortexm 16 48 64 120 168
|
||||
//go:generate go run gen-ws2812.go -arch=tinygoriscv 160 320
|
||||
//go:generate go run gen-ws2812-arm.go
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
//go:build tinygo.riscv32
|
||||
// +build tinygo.riscv32
|
||||
|
||||
package ws2812
|
||||
|
||||
import "machine"
|
||||
|
||||
// Send a single byte using the WS2812 protocol.
|
||||
func (d Device) WriteByte(c byte) error {
|
||||
switch machine.CPUFrequency() {
|
||||
case 160_000_000: // 160MHz, e.g. esp32c3
|
||||
d.writeByte160(c)
|
||||
return nil
|
||||
case 320_000_000: // 320MHz, e.g. fe310
|
||||
d.writeByte320(c)
|
||||
return nil
|
||||
default:
|
||||
return errUnknownClockSpeed
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user