Compare commits

..

25 Commits

Author SHA1 Message Date
sago35 8fc9dd0670 net/http: add length check 2022-12-25 21:54:24 +09:00
sago35 479beeeece WIP : chunked 2022-12-25 19:07:33 +09:00
sago35 2526660a96 WIP: no data 2022-12-25 19:07:17 +09:00
sago35 4213d6f582 net/http: refactor net/http/tinygo.go 2022-12-25 11:48:04 +09:00
sago35 81cf507e4e net/http: add support for RoundTripper 2022-12-25 11:41:36 +09:00
sago35 86cc0e31f1 rtl8720dn: add handling when connect fails 2022-12-25 11:30:49 +09:00
sago35 e3e95cacfe net/http: add PostForm() 2022-12-25 11:12:41 +09:00
deadprogram 8b3075fdba build: remove older format build tags
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-12-21 17:47:14 -05:00
Kenneth Bell 7d58709b7d bme280: improve config support 2022-12-20 11:13:43 +01:00
Jason Del Ponte 789bbbd89f Update DHT22 receive to use runtime/interrupt
Fixes #483 by updating the DHT22 device to use runtime/interrupt instead
of machine.UART1 for interrupt disabling while receiving signals from the
device.
2022-12-20 11:10:52 +01:00
Lucas Bremgartner ea944c8933 buzzer: no tone during rest 2022-12-19 22:01:39 +01:00
Lucas Bremgartner d27859453c buzzer: make all note durations float64 2022-12-19 22:01:39 +01:00
Damian Gryski 0ccd979f23 examples: fix odd if sequence found by static analysis 2022-12-04 21:26:47 +01:00
John Clark a888570c8c fix broken link for lora sx1261 2022-11-23 22:13:43 +01:00
Michael Meister 5b2c2f800d vl53l1x: Add getter for the effective SPAD count
Implement function to get the effective SPAD count.

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

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

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

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

* qmi8656c: update ReadTemperature signature

* Update README devices count
2022-10-02 14:14:37 +02:00
101 changed files with 1587 additions and 409 deletions
+4
View File
@@ -103,6 +103,8 @@ smoke-test:
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit-v2 ./examples/microbitmatrix/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
@@ -209,6 +211,8 @@ endif
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pico ./examples/qmi8658c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
+4 -3
View File
@@ -52,7 +52,7 @@ func main() {
## Currently supported devices
The following 83 devices are supported.
The following 90 devices are supported.
| Device Name | Interface Type |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
@@ -112,6 +112,7 @@ The following 83 devices are supported.
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
| [QMI8658C accelerometer/gyroscope](https://www.qstcorp.com/upload/pdf/202202/%EF%BC%88%E5%B7%B2%E4%BC%A0%EF%BC%89QMI8658C%20datasheet%20rev%200.9.pdf) | I2C |
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
| [RTL8720DN 2.4G/5G Dual Bands Wireless and BLE5.0](https://www.seeedstudio.com/Realtek8720DN-2-4G-5G-Dual-Bands-Wireless-and-BLE5-0-Combo-Module-p-4442.html) | UART |
| [SCD4x CO2 Sensor](https://sensirion.com/media/documents/C4B87CE6/627C2DCD/CD_DS_SCD40_SCD41_Datasheet_D1.pdf) | I2C |
@@ -140,10 +141,10 @@ The following 83 devices are supported.
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 2.9" e-paper display (V1)](https://www.waveshare.com/w/upload/e/e6/2.9inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI |
| [Waveshare GC9A01 TFT round display](https://www.waveshare.com/w/upload/5/5e/GC9A01A.pdf) | SPI |
| [Waveshare GC9A01 TFT round display](https://www.waveshare.com/w/upload/5/5e/GC9A01A.pdf) | SPI |
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-transceiv-ers/sx1261) | SPI |
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-connect/sx1261) | SPI |
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
## Contributing
-3
View File
@@ -1,10 +1,7 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package apds9960
import "tinygo.org/x/drivers"
// Configure sets up the APDS-9960 device.
func (d *Device) Configure(cfg Configuration) {
// configure device
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
package apds9960
+115 -5
View File
@@ -7,6 +7,7 @@ package bme280
import (
"math"
"time"
"tinygo.org/x/drivers"
)
@@ -33,11 +34,27 @@ type calibrationCoefficients struct {
h6 int8
}
type Oversampling byte
type Mode byte
type FilterCoefficient byte
type Period byte
// Config contains settings for filtering, sampling, and modes of operation
type Config struct {
Pressure Oversampling
Temperature Oversampling
Humidity Oversampling
Period Period
Mode Mode
IIR FilterCoefficient
}
// Device wraps an I2C connection to a BME280 device.
type Device struct {
bus drivers.I2C
Address uint16
calibrationCoefficients calibrationCoefficients
Config Config
}
// New creates a new BME280 connection. The I2C bus must already be
@@ -51,9 +68,34 @@ func New(bus drivers.I2C) Device {
}
}
// Configure sets up the device for communication and
// read the calibration coefficientes.
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration is the Indoor Navigation settings
// from the BME280 datasheet.
func (d *Device) Configure() {
d.ConfigureWithSettings(Config{})
}
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration if config is left at defaults is
// the Indoor Navigation settings from the BME280 datasheet.
func (d *Device) ConfigureWithSettings(config Config) {
d.Config = config
// If config is not initialized, use Indoor Navigation defaults.
if d.Config == (Config{}) {
d.Config = Config{
Mode: ModeNormal,
Period: Period0_5ms,
Temperature: Sampling2X,
Humidity: Sampling1X,
Pressure: Sampling16X,
IIR: Coeff16,
}
}
var data [24]byte
err := d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION, data[:])
@@ -93,10 +135,18 @@ func (d *Device) Configure() {
d.calibrationCoefficients.h4 = 0 + (int16(h2lsb[3]) << 4) | (int16(h2lsb[4] & 0x0F))
d.calibrationCoefficients.h5 = 0 + (int16(h2lsb[5]) << 4) | (int16(h2lsb[4]) >> 4)
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{0x3f})
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{0xB7})
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{0x00})
d.Reset()
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{byte(d.Config.Period<<5) | byte(d.Config.IIR<<2)})
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{byte(d.Config.Humidity)})
// Normal mode, start measuring now
if d.Config.Mode == ModeNormal {
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
}
// Connected returns whether a BME280 has been found.
@@ -112,6 +162,20 @@ func (d *Device) Reset() {
d.bus.WriteRegister(uint8(d.Address), CMD_RESET, []byte{0xB6})
}
// SetMode can set the device to Sleep, Normal or Forced mode
//
// Calling this method is optional, Configure can be used to set the
// initial mode if no mode change is desired. This method is most
// useful to switch between Sleep and Normal modes.
func (d *Device) SetMode(mode Mode) {
d.Config.Mode = mode
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d *Device) ReadTemperature() (int32, error) {
data, err := d.readData()
@@ -186,6 +250,16 @@ func readIntLE(msb byte, lsb byte) int16 {
// readData does a burst read from 0xF7 to 0xF0 according to the datasheet
// resulting in an slice with 8 bytes 0-2 = pressure / 3-5 = temperature / 6-7 = humidity
func (d *Device) readData() (data [8]byte, err error) {
if d.Config.Mode == ModeForced {
// Write the CTRL_MEAS register to trigger a measurement
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
time.Sleep(d.measurementDelay())
}
err = d.bus.ReadRegister(uint8(d.Address), REG_PRESSURE, data[:])
if err != nil {
println(err)
@@ -256,3 +330,39 @@ func (d *Device) calculateHumidity(data [8]byte, tFine int32) int32 {
return int32(100 * h)
}
// measurementDelay returns how much time each measurement will take
// on the device.
//
// This is used in forced mode to wait until a measurement is complete.
func (d *Device) measurementDelay() time.Duration {
const MeasOffset = 1250
const MeasDur = 2300
const HumMeasOffset = 575
const MeasScalingFactor = 1000
// delay is based on over-sampling rate - this table converts from
// setting to number samples
sampleRateConv := []int{0, 1, 2, 4, 8, 16}
tempOsr := 16
if d.Config.Temperature <= Sampling16X {
tempOsr = sampleRateConv[d.Config.Temperature]
}
presOsr := 16
if d.Config.Temperature <= Sampling16X {
presOsr = sampleRateConv[d.Config.Pressure]
}
humOsr := 16
if d.Config.Temperature <= Sampling16X {
humOsr = sampleRateConv[d.Config.Humidity]
}
max_delay := ((MeasOffset + (MeasDur * tempOsr) +
((MeasDur * presOsr) + HumMeasOffset) +
((MeasDur * humOsr) + HumMeasOffset)) / MeasScalingFactor)
return time.Duration(max_delay) * time.Millisecond
}
+44
View File
@@ -20,6 +20,50 @@ const (
CHIP_ID = 0x60
)
// Increasing sampling rate increases precision but also the wait time for measurements. The datasheet has a table of
// suggested values for oversampling, output data rates, and iir filter coefficients by use case.
const (
SamplingOff Oversampling = iota
Sampling1X
Sampling2X
Sampling4X
Sampling8X
Sampling16X
)
// In normal mode (the default) the sensor takes masurements periodically. In forced
// mode, the sensor takes a measurement only when requested.
//
// For use-cases with infrequent sampling, forced mode is more power efficient.
const (
ModeNormal Mode = 0x03
ModeForced Mode = 0x01
ModeSleep Mode = 0x00
)
// IIR filter coefficients, higher values means steadier measurements but slower reaction times
const (
Coeff0 FilterCoefficient = iota
Coeff2
Coeff4
Coeff8
Coeff16
)
// Period of standby in normal mode which controls how often measurements are taken
//
// Note Period10ms and Period20ms are out of sequence, but are per the datasheet
const (
Period0_5ms Period = 0b000
Period62_5ms = 0b001
Period125ms = 0b010
Period250ms = 0b011
Period500ms = 0b100
Period1000ms = 0b101
Period10ms = 0b110
Period20ms = 0b111
)
const (
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
)
+6
View File
@@ -54,6 +54,12 @@ func (l *Device) Tone(hz, duration float64) (err error) {
tempo := ((60 / l.BPM) * (duration * 1000))
// no tone during rest, just let the duration pass.
if hz == Rest {
time.Sleep(time.Duration(tempo) * time.Millisecond)
return
}
for i := 0.0; i < tempo*1000; i += tone * 2.0 {
if err = l.On(); err != nil {
return
+3 -3
View File
@@ -1,9 +1,9 @@
package buzzer
const (
Whole = 4
Half = 2
Quarter = 1
Whole = 4.0
Half = 2.0
Quarter = 1.0
Eighth = 0.500
)
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
-1
View File
@@ -1,5 +1,4 @@
//go:build mimxrt1062 || stm32f405 || atsamd51 || stm32f103xx || k210 || stm32f407
// +build mimxrt1062 stm32f405 atsamd51 stm32f103xx k210 stm32f407
package dht // import "tinygo.org/x/drivers/dht"
-1
View File
@@ -1,5 +1,4 @@
//go:build !mimxrt1062 && !stm32f405 && !atsamd51 && !stm32f103xx && !k210 && !stm32f407
// +build !mimxrt1062,!stm32f405,!atsamd51,!stm32f103xx,!k210,!stm32f407
package dht // import "tinygo.org/x/drivers/dht"
+3 -3
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
@@ -11,6 +10,7 @@ package dht // import "tinygo.org/x/drivers/dht"
import (
"machine"
"runtime/interrupt"
"time"
)
@@ -160,8 +160,8 @@ func (t *device) read() error {
// interrupts
func receiveSignals(pin machine.Pin, result []counter) {
i := uint8(0)
machine.UART1.Interrupt.Disable()
defer machine.UART1.Interrupt.Enable()
mask := interrupt.Disable()
defer interrupt.Restore(mask)
for ; i < 40; i++ {
result[i*2] = expectChange(pin, false)
result[i*2+1] = expectChange(pin, true)
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
package dht // import "tinygo.org/x/drivers/dht"
-1
View File
@@ -1,5 +1,4 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
@@ -1,5 +1,4 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21
// +build atsamd21
package initdisplay
-1
View File
@@ -1,5 +1,4 @@
//go:build feather_m0 || feather_m4 || feather_m4_can || feather_nrf52840 || feather_nrf52840_sense || feather_stm32f405 || feather_rp2040
// +build feather_m0 feather_m4 feather_m4_can feather_nrf52840 feather_nrf52840_sense feather_stm32f405 feather_rp2040
package initdisplay
-1
View File
@@ -1,5 +1,4 @@
//go:build m5stack
// +build m5stack
package initdisplay
@@ -1,5 +1,4 @@
//go:build m5stack_core2
// +build m5stack_core2
package initdisplay
-1
View File
@@ -1,5 +1,4 @@
//go:build pyportal
// +build pyportal
package initdisplay
@@ -1,5 +1,4 @@
//go:build wioterminal
// +build wioterminal
package initdisplay
+66
View File
@@ -0,0 +1,66 @@
// Connects to an QMI8658C I2C accelerometer/gyroscope and print the read data.
// This example was made with the "WaveShare RP2040 Round LCD 1.28in" in mind.
// For more infor about this development board:
// https://www.waveshare.com/wiki/RP2040-LCD-1.28
package main
import (
"machine"
"time"
imu "tinygo.org/x/drivers/qmi8658c"
)
func main() {
i2c := machine.I2C1
// This is the default pinout for the "WaveShare RP2040 Round LCD 1.28in"
err := i2c.Configure(machine.I2CConfig{
SDA: machine.GP6,
SCL: machine.GP7,
Frequency: 100000,
})
if err != nil {
println("unable to configure I2C:", err)
return
}
// Create a new device
d := imu.New(i2c)
// Check if the device is connected
if !d.Connected() {
println("unable to connect to sensor")
return
}
// This IMU has multiple configurations like output data rate, multiple
// measurements scales, low pass filters, low power modes, all the vailable
// values can be found in the datasheet and were defined at registers file.
// This is the default configuration which will be used if the `nil` value
// is passed do the `Configure` method.
config := imu.Config{
SPIMode: imu.SPI_4_WIRE,
SPIEndian: imu.SPI_BIG_ENDIAN,
SPIAutoInc: imu.SPI_AUTO_INC,
AccEnable: imu.ACC_ENABLE,
AccScale: imu.ACC_8G,
AccRate: imu.ACC_NORMAL_1000HZ,
AccLowPass: imu.ACC_LOW_PASS_2_62,
GyroEnable: imu.GYRO_FULL_ENABLE,
GyroScale: imu.GYRO_512DPS,
GyroRate: imu.GYRO_1000HZ,
GyroLowPass: imu.GYRO_LOW_PASS_2_62,
}
d.Configure(config)
// Read the accelation, rotation and temperature data and print them.
for {
acc_x, acc_y, acc_z := d.ReadAcceleration()
gyro_x, gyro_y, gyro_z := d.ReadRotation()
temp, _ := d.ReadTemperature()
println("-------------------------------")
println("acc:", acc_x, acc_y, acc_z)
println("gyro:", gyro_x, gyro_y, gyro_z)
println("temp:", temp)
time.Sleep(time.Millisecond * 100)
}
}
+1 -3
View File
@@ -100,9 +100,7 @@ func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(), nil
}
-1
View File
@@ -1,5 +1,4 @@
//go:build feather_m4 || feather_m4_can || feather_nrf52840
// +build feather_m4 feather_m4_can feather_nrf52840
package main
@@ -1,5 +1,4 @@
//go:build grandcentral_m4
// +build grandcentral_m4
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21 && !p1am_100
// +build atsamd21,!p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build p1am_100
// +build p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pygamer
// +build pygamer
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pyportal
// +build pyportal
package main
@@ -1,5 +1,4 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build wioterminal
// +build wioterminal
package main
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
package console
-1
View File
@@ -1,5 +1,4 @@
//go:build feather_m4 || feather_m4_can || feather_nrf52840
// +build feather_m4 feather_m4_can feather_nrf52840
package main
@@ -1,5 +1,4 @@
//go:build grandcentral_m4
// +build grandcentral_m4
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21 && !p1am_100
// +build atsamd21,!p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build p1am_100
// +build p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pygamer
// +build pygamer
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pyportal
// +build pyportal
package main
@@ -1,5 +1,4 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build wioterminal
// +build wioterminal
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build gnse
// +build gnse
/*
Generic Node Sensor Edition
-1
View File
@@ -1,5 +1,4 @@
//go:build lorae5
// +build lorae5
package radio
-1
View File
@@ -1,5 +1,4 @@
//go:build nucleowl55jc
// +build nucleowl55jc
/*
Nucleo WL55JC1
-1
View File
@@ -1,5 +1,4 @@
//go:build espat
// +build espat
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build rtl8720dn
// +build rtl8720dn
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build wifinina
// +build wifinina
package main
+1 -3
View File
@@ -111,9 +111,7 @@ func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(), nil
}
-1
View File
@@ -1,5 +1,4 @@
//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
+209
View File
@@ -0,0 +1,209 @@
package main
import (
"fmt"
"machine"
"strconv"
"time"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/wifinina"
)
// You can override the settings with the init() in another source code:
//
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// }
//
// Or use -ldflags option on tinygo command to set at compile-time:
//
// tinygo flash ... -ldflags '-X "main.ssid=xxx" -X "main.pass=xxx"' ...
//
var (
ssid string
pass string
)
var led = machine.LED
func main() {
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
spi := machine.NINA_SPI
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor := wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, subnet, gateway, err := adaptor.GetIP()
if err != nil {
return err
}
fmt.Printf("IP Address : %s\r\n", ip)
fmt.Printf("Mask : %s\r\n", subnet)
fmt.Printf("Gateway : %s\r\n", gateway)
http.UseDriver(adaptor)
http.HandleFunc("/", root)
http.HandleFunc("/hello", hello)
http.HandleFunc("/cnt", cnt)
http.HandleFunc("/6", sixlines)
http.HandleFunc("/off", LED_OFF)
http.HandleFunc("/on", LED_ON)
return http.ListenAndServe(":80", nil)
}
func root(w http.ResponseWriter, r *http.Request) {
access := 1
cookie, err := r.Cookie("access")
if err != nil {
if err == http.ErrNoCookie {
cookie = &http.Cookie{
Name: "access",
Value: "1",
}
} else {
http.Error(w, fmt.Sprintf("%s", err.Error()), http.StatusBadRequest)
return
}
} else {
v, err := strconv.ParseInt(cookie.Value, 10, 0)
if err != nil {
http.Error(w, fmt.Sprintf("invalid cookie.Value : %s", cookie.Value), http.StatusBadRequest)
return
}
cookie.Value = fmt.Sprintf("%d", v+1)
access = int(v) + 1
}
http.SetCookie(w, cookie)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `
<html>
<head>
<title>TinyGo HTTP Server</title>
<script language="javascript" type="text/javascript">
var counter = 0
function ledOn() { fetch("/on"); }
function ledOff() { fetch("/off"); }
function fetchCnt() { fetch("/cnt").then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); }
function incrCnt() { counter = counter + 1; fetch("/cnt?cnt=" + counter, { method: 'POST' }).then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); }
function setCnt() { fetch("/cnt", {
method: "POST",
body: "cnt=" + document.getElementsByName("cnt")[0].value,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}).then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); return false; }
function onLoad() { fetchCnt(); }
</script>
</head>
<body onLoad="onLoad()">
<h5>TinyGo HTTP Server</h5>
<p>
access: %d
</p>
<a href="/hello">/hello</a><br>
<a href="/6">/6</a><br>
<p>
LED<br>
<a href="javascript:ledOn();">/on</a><br>
<a href="javascript:ledOff();">/off</a><br>
</p>
<p>
<a href="/cnt">/cnt</a><br>
cnt: <span id="cnt"></span><br>
<a href="javascript:incrCnt()">incrCnt()</a><br>
<form id="form1" style="display: inline" onSubmit="return setCnt()">
<input type="text" name="cnt">
<input type="button" value="set cnt", onClick="setCnt()">
</form>
</p>
</body>
</html>
`, access)
}
func sixlines(w http.ResponseWriter, r *http.Request) {
// https://fukuno.jig.jp/3267
fmt.Fprint(w, `<body onload='onkeydown=e=>K=parseInt(e.key[5]||6,28)/3-8;Z=X=[B=A=12];Y=_=>`+
`{for(C=[q=c=i=4];f=i--*K;c-=!Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)])p=B[i];for(c?0:K+6?h+=K:B=C;`+
`i=K=q--;f+=Z[A+p])X[p=h+B[q]]=1;h+=A;if(f|B)for(Z=X,X=[l=228],B=[[-7,-20,6,h=17,-9,3,3][t=++t%7]-4,0,1,t-6?-A:2];l--;)`+
`for(l%A?l-=l%A*!Z[l]:(P++,c=l+=A);--c>A;)Z[c]=Z[c-A];for(S="";i<240;S+=X[i]|(X[i]=Z[i]|=++i%A<2|i>228)?i%A?"■":"■<br>":" ");`+
`D.innerHTML=S+P;setTimeout(Y,i-P)};Y(h=K=t=P=0)'id=D>`)
}
func LED_ON(w http.ResponseWriter, r *http.Request) {
led.High()
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "led.High()")
}
func LED_OFF(w http.ResponseWriter, r *http.Request) {
led.Low()
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "led.Low()")
}
func hello(w http.ResponseWriter, r *http.Request) {
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "hello")
}
var counter int
func cnt(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if r.Method == "POST" {
c := r.Form.Get("cnt")
if c != "" {
i64, _ := strconv.ParseInt(c, 0, 0)
counter = int(i64)
}
}
w.Header().Set(`Content-Type`, `application/json`)
fmt.Fprintf(w, `{"cnt": %d}`, counter)
}
func message(msg string) {
println(msg, "\r")
}
-1
View File
@@ -1,5 +1,4 @@
//go:build arduino
// +build arduino
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build digispark
// +build digispark
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build !digispark && !arduino && !qtpy && !m5stamp_c3 && !thingplus_rp2040
// +build !digispark,!arduino,!qtpy,!m5stamp_c3,!thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build qtpy || m5stamp_c3
// +build qtpy m5stamp_c3
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build qtpy
// +build qtpy
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51
// +build atsamd51
package flash
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package hts221
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
package hts221
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51 || atsame5x
// +build atsamd51 atsame5x
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build esp32
// +build esp32
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build nrf52840
// +build nrf52840
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build !esp32 && !atsamd51 && !atsame5x && !stm32f4 && !rp2040 && !nrf52840
// +build !esp32,!atsamd51,!atsame5x,!stm32f4,!rp2040,!nrf52840
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build rp2040
// +build rp2040
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build stm32f4
// +build stm32f4
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51
// +build atsamd51
package ili9341
-1
View File
@@ -1,5 +1,4 @@
//go:build !atsamd51 && !atsame5x && !atsamd21
// +build !atsamd51,!atsame5x,!atsamd21
package ili9341
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21
// +build atsamd21
package ili9341
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51 || atsame5x
// +build atsamd51 atsame5x
package ili9341
-1
View File
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
-1
View File
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build gofuzz
// +build gofuzz
package png
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package lps22hb
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
package lps22hb
+3 -3
View File
@@ -137,7 +137,7 @@ func (d *Device) Configure(cfg Configuration) (err error) {
// -1000000.
func (d *Device) ReadAcceleration() (x, y, z int32, err error) {
data := d.buf[:6]
err = d.bus.ReadRegister(uint8(d.AccelAddress), ACCEL_OUT_X_L_A, data)
err = d.bus.ReadRegister(uint8(d.AccelAddress), ACCEL_OUT_AUTO_INC, data)
if err != nil {
return
}
@@ -190,7 +190,7 @@ func (d *Device) ReadMagneticField() (x, y, z int32, err error) {
}
data := d.buf[0:6]
d.bus.ReadRegister(uint8(d.MagAddress), MAG_OUT_X_L_M, data)
d.bus.ReadRegister(uint8(d.MagAddress), MAG_OUT_AUTO_INC, data)
x = int32(int16((uint16(data[1])<<8 | uint16(data[0]))))
y = int32(int16((uint16(data[3])<<8 | uint16(data[2]))))
@@ -219,7 +219,7 @@ func (d *Device) ReadCompass() (h int32, err error) {
func (d *Device) ReadTemperature() (t int32, err error) {
data := d.buf[:2]
err = d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_L_A, data)
err = d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_AUTO_INC, data)
if err != nil {
return
}
+29 -20
View File
@@ -6,31 +6,40 @@ const (
ACCEL_ADDRESS = 0x19
MAG_ADDRESS = 0x1E
// i2C 8-bit subaddress (SUB): the 7 LSb represent the actual register address
// while the MSB enables address auto increment.
// If the MSb of the SUB field is 1, the SUB (register address) is
// automatically increased to allow multiple data read/writes.
ADDR_AUTO_INC_MASK = 0x80
// accelerometer registers.
ACCEL_WHO_AM_I = 0x0F
ACCEL_CTRL_REG1_A = 0x20
ACCEL_CTRL_REG4_A = 0x23
ACCEL_OUT_X_L_A = 0x28
ACCEL_OUT_X_H_A = 0x29
ACCEL_OUT_Y_L_A = 0x2A
ACCEL_OUT_Y_H_A = 0x2B
ACCEL_OUT_Z_L_A = 0x2C
ACCEL_OUT_Z_H_A = 0x2D
ACCEL_WHO_AM_I = 0x0F
ACCEL_CTRL_REG1_A = 0x20
ACCEL_CTRL_REG4_A = 0x23
ACCEL_OUT_X_L_A = 0x28
ACCEL_OUT_X_H_A = 0x29
ACCEL_OUT_Y_L_A = 0x2A
ACCEL_OUT_Y_H_A = 0x2B
ACCEL_OUT_Z_L_A = 0x2C
ACCEL_OUT_Z_H_A = 0x2D
ACCEL_OUT_AUTO_INC = ACCEL_OUT_X_L_A | ADDR_AUTO_INC_MASK
// magnetic sensor registers.
MAG_WHO_AM_I = 0x4F
MAG_MR_REG_M = 0x60
MAG_OUT_X_L_M = 0x68
MAG_OUT_X_H_M = 0x69
MAG_OUT_Y_L_M = 0x6A
MAG_OUT_Y_H_M = 0x6B
MAG_OUT_Z_L_M = 0x6C
MAG_OUT_Z_H_M = 0x6D
MAG_WHO_AM_I = 0x4F
MAG_MR_REG_M = 0x60
MAG_OUT_X_L_M = 0x68
MAG_OUT_X_H_M = 0x69
MAG_OUT_Y_L_M = 0x6A
MAG_OUT_Y_H_M = 0x6B
MAG_OUT_Z_L_M = 0x6C
MAG_OUT_Z_H_M = 0x6D
MAG_OUT_AUTO_INC = MAG_OUT_X_L_M | ADDR_AUTO_INC_MASK
// temperature sensor registers.
TEMP_CFG_REG_A = 0x1F
OUT_TEMP_L_A = 0x0C
OUT_TEMP_H_A = 0x0D
TEMP_CFG_REG_A = 0x1F
OUT_TEMP_L_A = 0x0C
OUT_TEMP_H_A = 0x0D
OUT_TEMP_AUTO_INC = OUT_TEMP_L_A | ADDR_AUTO_INC_MASK
// accelerometer power mode.
ACCEL_POWER_NORMAL = 0x00 // default
-1
View File
@@ -1,5 +1,4 @@
//go:build !xiao_ble
// +build !xiao_ble
package lsm6ds3tr
-1
View File
@@ -1,5 +1,4 @@
//go:build xiao_ble
// +build xiao_ble
package lsm6ds3tr
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package lsm9ds1
-1
View File
@@ -1,5 +1,4 @@
//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
+27 -63
View File
@@ -1,5 +1,4 @@
//go:build microbit
// +build microbit
// Package microbitmatrix implements a driver for the BBC micro:bit's LED matrix.
//
@@ -8,9 +7,12 @@ package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
import (
"machine"
"time"
)
// 4 rotation orientations (0, 90, 180, 270), CW (clock wise)
// 5 rows
// 5 cols
// target coordinates in machine rows (y) and cols (x)
var matrixRotations = [4][5][5][2]uint8{
{ // 0
{{0, 0}, {1, 3}, {0, 1}, {1, 4}, {0, 2}},
@@ -19,7 +21,7 @@ var matrixRotations = [4][5][5][2]uint8{
{{0, 7}, {0, 6}, {0, 5}, {0, 4}, {0, 3}},
{{2, 2}, {1, 6}, {2, 0}, {1, 5}, {2, 1}},
},
{ // 90 CCW
{ // 90 CW
{{0, 2}, {2, 7}, {1, 0}, {0, 3}, {2, 1}},
{{1, 4}, {2, 6}, {2, 8}, {0, 4}, {1, 5}},
{{0, 1}, {2, 5}, {1, 2}, {0, 5}, {2, 0}},
@@ -42,71 +44,33 @@ var matrixRotations = [4][5][5][2]uint8{
},
}
const (
ledRows = 3
ledCols = 9
)
type Device struct {
pin [12]machine.Pin
buffer [3][9]bool
pin [ledCols + ledRows]machine.Pin
buffer [ledRows][ledCols]int8
rotation uint8
}
// Configure sets up the device.
func (d *Device) Configure(cfg Config) {
d.SetRotation(cfg.Rotation)
func (d *Device) assignPins() {
d.pin[0] = machine.LED_COL_1
d.pin[1] = machine.LED_COL_2
d.pin[2] = machine.LED_COL_3
d.pin[3] = machine.LED_COL_4
d.pin[4] = machine.LED_COL_5
d.pin[5] = machine.LED_COL_6
d.pin[6] = machine.LED_COL_7
d.pin[7] = machine.LED_COL_8
d.pin[8] = machine.LED_COL_9
for i := machine.LED_COL_1; i <= machine.LED_ROW_3; i++ {
d.pin[i-machine.LED_COL_1] = i
d.pin[i-machine.LED_COL_1].Configure(machine.PinConfig{Mode: machine.PinOutput})
}
d.ClearDisplay()
d.DisableAll()
}
d.pin[9] = machine.LED_ROW_1
d.pin[10] = machine.LED_ROW_2
d.pin[11] = machine.LED_ROW_3
// Display sends the buffer (if any) to the screen.
func (d *Device) Display() error {
for row := 0; row < 3; row++ {
d.DisableAll()
d.pin[9+row].High()
for col := 0; col < 9; col++ {
if d.buffer[row][col] {
d.pin[col].Low()
}
}
time.Sleep(time.Millisecond * 2)
}
return nil
}
// ClearDisplay erases the internal buffer
func (d *Device) ClearDisplay() {
for row := 0; row < 3; row++ {
for col := 0; col < 9; col++ {
d.buffer[row][col] = false
}
for i := 0; i < len(d.pin); i++ {
d.pin[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
}
}
// DisableAll disables all the LEDs without modifying the buffer
func (d *Device) DisableAll() {
for i := machine.LED_COL_1; i <= machine.LED_COL_9; i++ {
d.pin[i-machine.LED_COL_1].High()
}
for i := machine.LED_ROW_1; i <= machine.LED_ROW_3; i++ {
d.pin[i-machine.LED_COL_1].Low()
}
}
// EnableAll enables all the LEDs without modifying the buffer
func (d *Device) EnableAll() {
for i := machine.LED_COL_1; i <= machine.LED_COL_9; i++ {
d.pin[i-machine.LED_COL_1].Low()
}
for i := machine.LED_ROW_1; i <= machine.LED_ROW_3; i++ {
d.pin[i-machine.LED_COL_1].High()
}
}
// Size returns the current size of the display.
func (d *Device) Size() (w, h int16) {
return 5, 5
}
+35 -83
View File
@@ -1,57 +1,61 @@
//go:build microbit_v2
// +build microbit_v2
// Package microbitmatrix implements a driver for the BBC micro:bit version 2 LED matrix.
//
// Schematic:
// Schematic: https://github.com/microbit-foundation/microbit-v2-hardware/blob/main/V2.00/MicroBit_V2.0.0_S_schematic.PDF
package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
import (
"machine"
"time"
)
// 4 rotation orientations (0, 90, 180, 270), CW (clock wise)
// 5 rows
// 5 cols
// target coordinates in machine rows (y) and cols (x)
var matrixRotations = [4][5][5][2]uint8{
{ // 0
{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}},
{{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}},
{{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}},
{{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}},
{{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}},
},
{ // 90 CCW
{{4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}},
{{3, 0}, {3, 1}, {3, 2}, {3, 3}, {3, 4}},
{{2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}},
{{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}},
{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}},
{{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}},
{{2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}},
{{3, 0}, {3, 1}, {3, 2}, {3, 3}, {3, 4}},
{{4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}},
},
{ // 90 CW
{{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}},
{{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}},
{{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}},
{{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}},
{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}},
},
{ // 180
{{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
{{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
{{4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
{{4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
{{4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
{{4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}},
{{3, 4}, {3, 3}, {3, 2}, {3, 1}, {3, 0}},
{{2, 4}, {2, 3}, {2, 2}, {2, 1}, {2, 0}},
{{1, 4}, {1, 3}, {1, 2}, {1, 1}, {1, 0}},
{{0, 4}, {0, 3}, {0, 2}, {0, 1}, {0, 0}},
},
{ // 270
{{0, 4}, {0, 3}, {0, 2}, {0, 1}, {0, 0}},
{{1, 4}, {1, 3}, {1, 2}, {1, 1}, {1, 0}},
{{2, 4}, {2, 3}, {2, 2}, {2, 1}, {2, 0}},
{{3, 4}, {3, 3}, {3, 2}, {3, 1}, {3, 0}},
{{4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}},
{{4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
{{4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
{{4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
{{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
{{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
},
}
const (
ledRows = 5
ledCols = 5
)
type Device struct {
pin [10]machine.Pin
buffer [5][5]bool
pin [ledCols + ledRows]machine.Pin
buffer [ledRows][ledCols]int8
rotation uint8
}
// Configure sets up the device.
func (d *Device) Configure(cfg Config) {
d.SetRotation(cfg.Rotation)
func (d *Device) assignPins() {
d.pin[0] = machine.LED_COL_1
d.pin[1] = machine.LED_COL_2
d.pin[2] = machine.LED_COL_3
@@ -64,59 +68,7 @@ func (d *Device) Configure(cfg Config) {
d.pin[8] = machine.LED_ROW_4
d.pin[9] = machine.LED_ROW_5
for i := 0; i < 10; i++ {
for i := 0; i < len(d.pin); i++ {
d.pin[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
}
d.ClearDisplay()
d.DisableAll()
}
// Display sends the buffer (if any) to the screen.
func (d *Device) Display() error {
for x := 0; x < 5; x++ {
d.DisableAll()
d.pin[x].Low()
for y := 0; y < 5; y++ {
if d.buffer[x][y] {
d.pin[5+y].High()
} else {
d.pin[5+y].Low()
}
}
time.Sleep(time.Millisecond * 4)
}
return nil
}
// ClearDisplay erases the internal buffer
func (d *Device) ClearDisplay() {
for row := 0; row < 5; row++ {
for col := 0; col < 5; col++ {
d.buffer[row][col] = false
}
}
}
// DisableAll disables all the LEDs without modifying the buffer
func (d *Device) DisableAll() {
for i := 0; i < 5; i++ {
d.pin[i].High()
d.pin[5+i].Low()
}
}
// EnableAll enables all the LEDs without modifying the buffer
func (d *Device) EnableAll() {
for i := 0; i < 5; i++ {
d.pin[i].Low()
d.pin[5+i].High()
}
}
// Size returns the current size of the display.
func (d *Device) Size() (w, h int16) {
return 5, 5
}
+179 -8
View File
@@ -1,42 +1,213 @@
// Package microbitmatrix implements a driver for the BBC micro:bit's LED matrix.
//
// Schematic: https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf
package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
import (
"image/color"
"time"
)
type Config struct {
// Rotation of the LED matrix.
//
// Valid values:
//
// 0: regular orientation, (0 degree rotation)
// 1: 90 degree rotation clock wise
// 2: 180 degree rotation clock wise
// 3: 270 degree rotation clock wise
Rotation uint8
}
const (
RotationNormal = 0
Rotation90 = 1
Rotation180 = 2
Rotation270 = 3
)
// New returns a new microbitmatrix driver.
func New() Device {
return Device{}
}
// SetRotation changes the rotation of the LED matrix
// Configure sets up the device.
func (d *Device) Configure(cfg Config) {
d.SetRotation(cfg.Rotation)
d.assignPins()
d.ClearDisplay()
d.DisableAll()
}
// SetRotation changes the rotation of the LED matrix.
//
// Valid values for rotation:
//
// 0: regular orientation, (0 degree rotation)
// 1: 90 degree rotation clock wise
// 2: 180 degree rotation clock wise
// 3: 270 degree rotation clock wise
func (d *Device) SetRotation(rotation uint8) {
d.rotation = rotation % 4
}
// Source:
// https://github.com/bbcmicrobit/micropython/blob/1252f887ddc790676bf9314a136bd17650b9c36c/source/microbit/microbitdisplay.cpp#L282
var renderTimings = []time.Duration{
0, // Bright, Ticks Duration, Relative power
2, // 1, 2, 32µs, inf
2, // 2, 4, 64µs, 200%
4, // 3, 8, 128µs, 200%
7, // 4, 15, 240µs, 187%
13, // 5, 28, 448µs, 187%
25, // 6, 53, 848µs, 189%
49, // 7, 102, 1632µs, 192%
97, // 8, 199, 3184µs, 195%
}
// Source:
// https://github.com/bbcmicrobit/micropython/blob/1252f887ddc790676bf9314a136bd17650b9c36c/source/microbit/microbitdisplay.cpp#L368
const tickDuration = 16 * time.Microsecond
const (
rowIdx = 0
colIdx = 1
)
// SetPixel modifies the internal buffer in a single pixel.
//
// The alpha channel of the RGBA is used to control the brightness of the LED
// in 9 different levels.
//
// alpha channel, brightness level
// 0 - 27, 9 (no transparency = highest brightness)
// 28 - 55, 8
// 56 - 83, 7
// 84 - 111, 6
// 112 - 139, 5
// 140 - 167, 4
// 168 - 195, 3
// 196 - 223, 2
// 224 - 251, 1 (very high transparency = lowest brightness)
// 252 - 255, 0 (full transparency = off)
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
if x < 0 || x >= 5 || y < 0 || y >= 5 {
return
}
col := x
row := y
if c.R != 0 || c.G != 0 || c.B != 0 {
d.buffer[matrixRotations[d.rotation][y][x][0]][matrixRotations[d.rotation][y][x][1]] = true
d.buffer[matrixRotations[d.rotation][row][col][rowIdx]][matrixRotations[d.rotation][row][col][colIdx]] = brightness(c.A)
} else {
d.buffer[matrixRotations[d.rotation][y][x][0]][matrixRotations[d.rotation][y][x][1]] = false
d.buffer[matrixRotations[d.rotation][row][col][rowIdx]][matrixRotations[d.rotation][row][col][colIdx]] = 0
}
}
// GetPixel returns if the specific pixels is enabled
const (
brightnessLevels = 9
brightnessDivider = int8(255 / brightnessLevels)
)
var (
Brightness0 = color.RGBA{R: 0, G: 0, B: 0, A: 0}
Brightness1 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*1}
Brightness2 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*2}
Brightness3 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*3}
Brightness4 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*4}
Brightness5 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*5}
Brightness6 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*6}
Brightness7 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*7}
Brightness8 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*8}
Brightness9 = color.RGBA{R: 255, G: 255, B: 255, A: 255 - uint8(brightnessDivider)*9}
BrightnessOff = Brightness0
BrightnessFull = Brightness9
)
func brightness(alpha uint8) int8 {
return brightnessLevels - int8(alpha/uint8(brightnessDivider))
}
// GetPixel returns if the specific pixels is enabled.
func (d *Device) GetPixel(x int16, y int16) bool {
if x < 0 || x >= 5 || y < 0 || y >= 5 {
return false
}
return d.buffer[matrixRotations[d.rotation][y][x][0]][matrixRotations[d.rotation][y][x][1]]
col := x
row := y
return d.buffer[matrixRotations[d.rotation][row][col][rowIdx]][matrixRotations[d.rotation][row][col][colIdx]] > 0
}
const displayRefreshDelay = 8 * time.Millisecond
// Display sends the buffer (if any) to the screen.
func (d *Device) Display() error {
var displayBuffer [ledRows][ledCols]int8
for row := 0; row < ledRows; row++ {
for col := 0; col < ledCols; col++ {
displayBuffer[row][col] = d.buffer[row][col]
}
}
for row := 0; row < ledRows; row++ {
d.DisableAll()
d.pin[ledCols+row].High()
for col := 0; col < ledCols; col++ {
if displayBuffer[row][col] > 0 {
d.pin[col].Low()
}
}
then := time.Now()
var offset time.Duration = 0
for _, ticks := range renderTimings {
for time.Since(then).Nanoseconds() < int64(ticks*tickDuration+offset) {
time.Sleep(offset / 10)
}
offset += ticks + tickDuration
for col := 0; col < ledCols; col++ {
displayBuffer[row][col]--
if displayBuffer[row][col] <= 0 {
d.pin[col].High()
}
}
}
}
time.Sleep(displayRefreshDelay)
return nil
}
// ClearDisplay erases the internal buffer.
func (d *Device) ClearDisplay() {
for row := 0; row < ledRows; row++ {
for col := 0; col < ledCols; col++ {
d.buffer[row][col] = 0
}
}
}
// DisableAll disables all the LEDs without modifying the buffer.
func (d *Device) DisableAll() {
for i := 0; i < ledCols; i++ {
d.pin[i].High()
}
for i := 0; i < ledRows; i++ {
d.pin[ledCols+i].Low()
}
}
// EnableAll enables all the LEDs without modifying the buffer.
func (d *Device) EnableAll() {
for i := 0; i < ledCols; i++ {
d.pin[i].Low()
}
for i := 0; i < ledRows; i++ {
d.pin[ledCols+i].High()
}
}
// Size returns the current size of the display.
func (d *Device) Size() (w, h int16) {
return 5, 5
}
+2 -2
View File
@@ -31,8 +31,8 @@ func (d Device) Connected() bool {
}
// Configure sets up the device for communication.
func (d Device) Configure() {
d.bus.WriteRegister(uint8(d.Address), PWR_MGMT_1, []uint8{0})
func (d Device) Configure() error {
return d.bus.WriteRegister(uint8(d.Address), PWR_MGMT_1, []uint8{0})
}
// ReadAcceleration reads the current acceleration from the device and returns
+40
View File
@@ -2,6 +2,8 @@ package http
import (
"io"
"net/url"
"strings"
"time"
)
@@ -211,3 +213,41 @@ func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response,
req.Header.Set("Content-Type", contentType)
return c.Do(req)
}
// PostForm issues a POST to the specified URL, with data's keys and
// values URL-encoded as the request body.
//
// The Content-Type header is set to application/x-www-form-urlencoded.
// To set other headers, use NewRequest and DefaultClient.Do.
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
//
// PostForm is a wrapper around DefaultClient.PostForm.
//
// See the Client.Do method documentation for details on how redirects
// are handled.
//
// To make a request with a specified context.Context, use NewRequestWithContext
// and DefaultClient.Do.
func PostForm(url string, data url.Values) (resp *Response, err error) {
return DefaultClient.PostForm(url, data)
}
// PostForm issues a POST to the specified URL,
// with data's keys and values URL-encoded as the request body.
//
// The Content-Type header is set to application/x-www-form-urlencoded.
// To set other headers, use NewRequest and Client.Do.
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
//
// See the Client.Do method documentation for details on how redirects
// are handled.
//
// To make a request with a specified context.Context, use NewRequestWithContext
// and Client.Do.
func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
+140 -123
View File
@@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"io"
"net/textproto"
"strconv"
"strings"
"time"
@@ -25,17 +26,43 @@ func (c *Client) Do(req *Request) (*Response, error) {
req.AddCookie(cookie)
}
}
transport := c.Transport
if transport == nil {
transport = DefaultTransport
}
res, err := transport.RoundTrip(req)
if c.Jar != nil {
if rc := res.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
}
}
return res, err
}
type Transport struct {
}
var DefaultTransport RoundTripper
func init() {
DefaultTransport = &Transport{}
}
func (t *Transport) RoundTrip(req *Request) (*Response, error) {
switch req.URL.Scheme {
case "http":
return c.doHTTP(req)
return t.doHTTP(req)
case "https":
return c.doHTTPS(req)
return t.doHTTPS(req)
default:
return nil, fmt.Errorf("invalid schemer : %s", req.URL.Scheme)
}
}
func (c *Client) doHTTP(req *Request) (*Response, error) {
func (t *Transport) doHTTP(req *Request) (*Response, error) {
// make TCP connection
ip := net.ParseIP(req.URL.Hostname())
port := 80
@@ -106,10 +133,10 @@ func (c *Client) doHTTP(req *Request) (*Response, error) {
}
return c.doResp(conn, req)
return t.doResp(conn, req)
}
func (c *Client) doHTTPS(req *Request) (*Response, error) {
func (t *Transport) doHTTPS(req *Request) (*Response, error) {
conn, err := tls.Dial("tcp", req.URL.Host, nil)
retry := 0
for ; err != nil; conn, err = tls.Dial("tcp", req.URL.Host, nil) {
@@ -167,141 +194,131 @@ func (c *Client) doHTTPS(req *Request) (*Response, error) {
}
return c.doResp(conn, req)
return t.doResp(conn, req)
}
func (c *Client) doResp(conn net.Conn, req *Request) (*Response, error) {
func (t *Transport) doResp(conn net.Conn, req *Request) (*Response, error) {
resp := &Response{
Header: map[string][]string{},
}
// Header
var scanner *bufio.Scanner
cont := true
ofs := 0
remain := int64(0)
for cont {
for n, err := conn.Read(buf[ofs:]); n > 0; n, err = conn.Read(buf[ofs:]) {
if err != nil {
println("Read error: " + err.Error())
} else {
// Take care of the case where "\r\n\r\n" is on the boundary of a buffer
start := ofs
if start > 3 {
start -= 3
}
idx := bytes.Index(buf[start:ofs+n], []byte("\r\n\r\n"))
if idx == -1 {
ofs += n
continue
}
idx += start + 4
br := bufio.NewReader(conn)
tp := textproto.NewReader(br)
scanner = bufio.NewScanner(bytes.NewReader(buf[0 : ofs+n]))
if resp.Status == "" && scanner.Scan() {
status := strings.SplitN(scanner.Text(), " ", 2)
if len(status) != 2 {
conn.Close()
return nil, fmt.Errorf("invalid status : %q", scanner.Text())
}
resp.Proto = status[0]
fmt.Sscanf(status[0], "HTTP/%d.%d", &resp.ProtoMajor, &resp.ProtoMinor)
resp.Status = status[1]
fmt.Sscanf(status[1], "%d", &resp.StatusCode)
}
for scanner.Scan() {
text := scanner.Text()
if text == "" {
// end of header
if idx < n+ofs {
ofs = ofs + n - idx
for i := 0; i < ofs; i++ {
buf[i] = buf[i+idx]
}
} else {
ofs = 0
}
break
} else {
header := strings.SplitN(text, ": ", 2)
if len(header) != 2 {
conn.Close()
return nil, fmt.Errorf("invalid header : %q", text)
}
if resp.Header.Get(header[0]) == "" {
resp.Header.Set(header[0], header[1])
} else {
resp.Header.Add(header[0], header[1])
}
if strings.ToLower(header[0]) == "content-length" {
resp.ContentLength, err = strconv.ParseInt(header[1], 10, 64)
if err != nil {
conn.Close()
return nil, err
}
remain = resp.ContentLength
}
}
}
cont = false
break
}
}
}
// Body
remain -= int64(ofs)
if remain <= 0 {
resp.Body = io.NopCloser(bytes.NewReader(buf[:ofs]))
if c.Jar != nil {
if rc := resp.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
}
}
return resp, conn.Close()
}
cont = true
lastRequestTime := time.Now()
for cont {
for {
end := ofs + 0x400
if len(buf) < end {
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", end)
}
n, err := conn.Read(buf[ofs : ofs+0x400])
if err != nil {
return nil, err
}
if n == 0 {
for {
line, err := tp.ReadLine()
if err != nil {
if err == io.ErrNoProgress {
// default: no timeout
continue
}
conn.Close()
return nil, err
}
status := strings.SplitN(line, " ", 2)
if len(status) != 2 {
conn.Close()
return nil, fmt.Errorf("invalid status : %q", line)
}
resp.Proto = status[0]
fmt.Sscanf(status[0], "HTTP/%d.%d", &resp.ProtoMajor, &resp.ProtoMinor)
resp.Status = status[1]
fmt.Sscanf(status[1], "%d", &resp.StatusCode)
break
}
m, err := tp.ReadMIMEHeader()
if err != nil {
conn.Close()
return nil, err
}
for k, v := range m {
//fmt.Printf("%s: %s\n", k, v)
if strings.ToLower(k) == "content-length" {
resp.ContentLength, err = strconv.ParseInt(v[0], 10, 64)
if err != nil {
conn.Close()
return nil, err
} else {
ofs += n
remain -= int64(n)
if remain <= 0 {
resp.Body = io.NopCloser(bytes.NewReader(buf[:ofs]))
cont = false
break
}
if time.Now().Sub(lastRequestTime).Milliseconds() >= 1000 {
conn.Close()
return nil, fmt.Errorf("time out")
}
}
}
if resp.Header.Get(k) == "" {
resp.Header.Set(k, v[0])
v = v[1:]
}
for _, vv := range v {
resp.Header.Add(k, vv)
}
}
if c.Jar != nil {
if rc := resp.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
if resp.Header.Get("Transfer-Encoding") == "chunked" {
// chunked
cur := 0
end := 0
for {
length := 0
if len(buf) < cur+6 {
// This is not a very accurate check, but in many cases it should be fine.
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", cur+6)
}
for i := 0; ; i++ {
buf[cur+i], err = br.ReadByte()
if err != nil {
conn.Close()
return nil, err
}
length = i + 1
if i > 1 && buf[cur+i-1] == '\r' && buf[cur+i] == '\n' {
break
}
}
//fmt.Printf("cur:%d length:%d\n", cur, length)
size, err := strconv.ParseInt(string(buf[cur:cur+length-2]), 16, 64)
if err != nil {
conn.Close()
return nil, err
}
//cur += length
//fmt.Printf("cur:%d length:%d size:%d\n", cur, length, size)
end = cur + int(size) + 2 // size + 2 (\r\n)
if len(buf) < end {
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", end)
}
for i := 0; i < int(size)+2; i++ {
buf[cur+i], err = br.ReadByte()
if err != nil {
conn.Close()
return nil, err
}
}
cur += int(size)
if size == 0 {
end = end - 2
break
}
}
//fmt.Printf("%q\n", buf[:end])
resp.Body = io.NopCloser(bytes.NewReader(buf[:end]))
} else {
end := int(resp.ContentLength)
if len(buf) < end {
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", end)
}
for i := 0; i < end; i++ {
buf[i], err = br.ReadByte()
if err != nil {
conn.Close()
return nil, err
}
}
resp.Body = io.NopCloser(bytes.NewReader(buf[:end]))
}
return resp, conn.Close()
+190
View File
@@ -0,0 +1,190 @@
// Package qmi8658c provides a driver for the QMI8658C accelerometer and gyroscope
// made by QST Solutions.
//
// Datasheet:
// https://www.qstcorp.com/upload/pdf/202202/%EF%BC%88%E5%B7%B2%E4%BC%A0%EF%BC%89QMI8658C%20datasheet%20rev%200.9.pdf
package qmi8656c
import "tinygo.org/x/drivers"
// Device wraps the I2C connection to the QMIC8658 sensor
type Device struct {
bus drivers.I2C
Address uint16
AccLsbDiv uint16
GyroLsbDiv uint16
}
type Config struct {
// SPI Config
SPIMode byte // One of SPI_X_WIRE
SPIEndian byte // One of SPI_XXX_ENDIAN
SPIAutoInc byte // One of SPI_NOT_AUTO_INC or SPI_AUTO_INC
// Accelerometer
AccEnable byte // One of ACC_ENABLE or ACC_DISABLE
AccScale byte // One of ACC_XG
AccRate byte // One of ACC_XX_YYHZ
AccLowPass byte // One of ACC_LOW_PASS_X
// Gyro
GyroEnable byte // One of GYRO_X_ENABLE or GYRO_DISABLE
GyroScale byte // One of GYRO_XDPS
GyroRate byte // One of GYRO_X_YHZ
GyroLowPass byte // One of GYRO_LOW_PASS_X
}
// Create a new device with the I2C passed, correct address and nil values for
// AccLsbDiv and GyroLsbDiv, which will be corrected based on the config.
func New(bus drivers.I2C) Device {
return Device{
bus,
Address,
1,
1,
}
}
// Check if the device is connected by calling WHO_AM_I and checking the
// default identifier.
func (d *Device) Connected() bool {
data := []byte{0}
d.ReadRegister(WHO_AM_I, data)
return data[0] == IDENTIFIER
}
// Create a basic default configuration that works with the "WaveShare RP2040
// Round LCD 1.28in".
func DefaultConfig() (cfg Config) {
return Config{
SPIMode: SPI_4_WIRE,
SPIEndian: SPI_BIG_ENDIAN,
SPIAutoInc: SPI_AUTO_INC,
AccEnable: ACC_ENABLE,
AccScale: ACC_8G,
AccRate: ACC_NORMAL_1000HZ,
AccLowPass: ACC_LOW_PASS_2_62,
GyroEnable: GYRO_FULL_ENABLE,
GyroScale: GYRO_512DPS,
GyroRate: GYRO_1000HZ,
GyroLowPass: GYRO_LOW_PASS_2_62,
}
}
// Check if the user has defined a desired configuration, if not uses the
// DefaultConfig, then defines the AccLsbDiv and GyroLsbDiv based on the
// configurations and, finally, send the commands and configure the IMU.
func (d *Device) Configure(cfg Config) {
if cfg == (Config{}) {
cfg = DefaultConfig()
}
var val uint16
// Setting accelerometer LSB
switch cfg.AccScale {
case ACC_2G:
d.AccLsbDiv = 1 << 14
case ACC_4G:
d.AccLsbDiv = 1 << 13
case ACC_8G:
d.AccLsbDiv = 1 << 12
case ACC_16G:
d.AccLsbDiv = 1 << 11
default:
d.AccLsbDiv = 1 << 12
}
// Setting gyro LSB
switch cfg.GyroScale {
case GYRO_16DPS:
d.GyroLsbDiv = 2048
case GYRO_32DPS:
d.GyroLsbDiv = 1024
case GYRO_64DPS:
d.GyroLsbDiv = 512
case GYRO_128DPS:
d.GyroLsbDiv = 256
case GYRO_256DPS:
d.GyroLsbDiv = 128
case GYRO_512DPS:
d.GyroLsbDiv = 64
case GYRO_1024DPS:
d.GyroLsbDiv = 32
case GYRO_2048DPS:
d.GyroLsbDiv = 16
default:
d.GyroLsbDiv = 64
}
// SPI Modes
val = uint16((cfg.SPIMode | cfg.SPIEndian | cfg.SPIAutoInc))
d.WriteRegister(CTRL1, val)
// Accelerometer config
val = uint16(cfg.AccScale | cfg.AccRate)
d.WriteRegister(CTRL2, val)
// Gyro config
val = uint16(cfg.GyroScale | cfg.GyroRate)
d.WriteRegister(CTRL3, val)
// Sensor DSP config
val = uint16(cfg.GyroLowPass | cfg.AccLowPass)
d.WriteRegister(CTRL5, val)
// Sensors config
val = uint16(cfg.GyroEnable | cfg.AccEnable)
d.WriteRegister(CTRL7, val)
}
// Read the acceleration from the sensor, the values returned are in mg
// (milli gravity), which means that 1000 = 1g.
func (d *Device) ReadAcceleration() (x int32, y int32, z int32) {
data := make([]byte, 6)
raw := make([]int32, 3)
d.ReadRegister(ACC_XOUT_L, data)
for i := range raw {
raw[i] = int32(uint16(data[(2*i+1)])<<8 | uint16(data[i]))
if raw[i] >= 32767 {
raw[i] = raw[i] - 65535
}
}
x = -raw[0] * 1000 / int32(d.AccLsbDiv)
y = -raw[1] * 1000 / int32(d.AccLsbDiv)
z = -raw[2] * 1000 / int32(d.AccLsbDiv)
return x, y, z
}
// Read the rotation from the sensor, the values returned are in mdeg/sec
// (milli degress/second), which means that a full rotation is 360000.
func (d *Device) ReadRotation() (x int32, y int32, z int32) {
data := make([]byte, 6)
raw := make([]int32, 3)
d.ReadRegister(GYRO_XOUT_L, data)
for i := range raw {
raw[i] = int32(uint16(data[(2*i+1)])<<8 | uint16(data[i]))
if raw[i] >= 32767 {
raw[i] = raw[i] - 65535
}
}
x = raw[0] * 1000 / int32(d.GyroLsbDiv)
y = raw[1] * 1000 / int32(d.GyroLsbDiv)
z = raw[2] * 1000 / int32(d.GyroLsbDiv)
return x, y, z
}
// Read the temperature from the sensor, the values returned are in
// millidegrees Celsius.
func (d *Device) ReadTemperature() (int32, error) {
data := make([]byte, 2)
err := d.ReadRegister(TEMP_OUT_L, data)
if err != nil {
return 0, err
}
raw := uint16(data[1])<<8 | uint16(data[0])
t := int32(raw) * 1000 / 256
return t, err
}
// Convenience method to read the register and avoid repetition.
func (d *Device) ReadRegister(reg uint8, buf []byte) error {
return d.bus.ReadRegister(uint8(d.Address), reg, buf)
}
// Convenience method to write the register and avoid repetition.
func (d *Device) WriteRegister(reg uint8, v uint16) error {
data := []byte{byte(v)}
err := d.bus.WriteRegister(uint8(d.Address), reg, data)
return err
}
+143
View File
@@ -0,0 +1,143 @@
package qmi8656c
// The I2C address that the sensor listens to.
const Address = 0x6B
const (
// Who am I
WHO_AM_I = 0x00
IDENTIFIER = 0x05
// Configuration registers
CTRL1 = 0x02 // SPI Modes
CTRL2 = 0x03 // Accelerometer config
CTRL3 = 0x04 // Gyro config
CTRL4 = 0x05 // Magnetometer config (ignored)
CTRL5 = 0x06 // Sensor DSP config
CTRL6 = 0x07 // Motion on Demand (ignored)
CTRL7 = 0x08 // Sensors config
// Interface config (CTRL1)
SPI_4_WIRE = 0x00
SPI_3_WIRE = 0x80
SPI_NOT_AUTO_INC = 0x00
SPI_AUTO_INC = 0x40
SPI_LITTLE_ENDIAN = 0x00
SPI_BIG_ENDIAN = 0x20
// Accelerometer scale config (CTRL2-H)
ACC_SELF_TEST = 0x80
// Accelerometer scale config (CTRL2-H)
ACC_2G = 0x00
ACC_4G = 0x10
ACC_8G = 0x20
ACC_16G = 0x30
// Accelerometer output data rate (ODR) config (CTRL2-L)
ACC_NORMAL_8000HZ = 0x00
ACC_NORMAL_4000HZ = 0x01
ACC_NORMAL_2000HZ = 0x02
ACC_NORMAL_1000HZ = 0x03
ACC_NORMAL_500HZ = 0x04
ACC_NORMAL_250HZ = 0x05
ACC_NORMAL_125HZ = 0x06
ACC_NORMAL_62HZ = 0x07
ACC_NORMAL_31HZ = 0x08
ACC_LOW_POWER_128HZ = 0x0C
ACC_LOW_POWER_21HZ = 0x0D
ACC_LOW_POWER_11HZ = 0x0E
ACC_LOW_POWER_3HZ = 0x0F
// Gyro scale config (CTRL3-H)
GYRO_SELF_TEST = 0x80
// Gyro scale config (CTRL3-H)
GYRO_16DPS = 0x00
GYRO_32DPS = 0x10
GYRO_64DPS = 0x20
GYRO_128DPS = 0x30
GYRO_256DPS = 0x40
GYRO_512DPS = 0x50
GYRO_1024DPS = 0x60
GYRO_2048DPS = 0x70
// Gyro output data rate (ODR) config (CTRL3-L)
GYRO_8000HZ = 0x00
GYRO_4000HZ = 0x01
GYRO_2000HZ = 0x02
GYRO_1000HZ = 0x03
GYRO_500HZ = 0x04
GYRO_250HZ = 0x05
GYRO_125HZ = 0x06
GYRO_62HZ = 0x07
GYRO_31HZ = 0x08
// Gyro DSP config (CTRL4-H)
GYRO_LOW_PASS_OFF = 0x00 // Disabled
GYRO_LOW_PASS_2_62 = 0x10 // 2.62% of output data rate (ODR)
GYRO_LOW_PASS_3_59 = 0x30 // 3.59% of output data rate (ODR)
GYRO_LOW_PASS_5_32 = 0x50 // 5.32% of output data rate (ODR)
GYRO_LOW_PASS_14 = 0x70 // 14% of output data rate (ODR)
// Accelerometer DSP config (CTRL4-L)
ACC_LOW_PASS_OFF = 0x00 // Disabled
ACC_LOW_PASS_2_62 = 0x01 // 2.62% of output data rate (ODR)
ACC_LOW_PASS_3_59 = 0x03 // 3.59% of output data rate (ODR)
ACC_LOW_PASS_5_32 = 0x05 // 5.32% of output data rate (ODR)
ACC_LOW_PASS_14 = 0x07 // 14% of output data rate (ODR)
// Motion on demand (MOD) (CTRL6)
MOD_DISABLE = 0x00
MOD_ENABLE = 0x80
// Enable sensors (CTRL7)
GYRO_DISABLE = 0x00
GYRO_FULL_ENABLE = 0x02
GYRO_SNOOZE_ENABLE = 0x12
ACC_DISABLE = 0x00
ACC_ENABLE = 0x01
// Timestamp Outputs Register Adresses
TIMESTAMP_OUT_L = 0x30
TIMESTAMP_OUT_M = 0x31
TIMESTAMP_OUT_H = 0x32
// Temperature Outputs Register Adresses
TEMP_OUT_L = 0x33
TEMP_OUT_H = 0x34
// Acceleration Outputs Register Adresses
ACC_XOUT_L = 0x35
ACC_XOUT_H = 0x36
ACC_YOUT_L = 0x37
ACC_YOUT_H = 0x38
ACC_ZOUT_L = 0x39
ACC_ZOUT_H = 0x3A
// Angular Rate Outputs Register Adresses
GYRO_XOUT_L = 0x3B
GYRO_XOUT_H = 0x3C
GYRO_YOUT_L = 0x3D
GYRO_YOUT_H = 0x3E
GYRO_ZOUT_L = 0x3F
GYRO_ZOUT_H = 0x40
// Quaternion Outputs Register Adresses
DELTA_QUAT_WOUT_L = 0x49
DELTA_QUAT_WOUT_H = 0x4A
DELTA_QUAT_XOUT_L = 0x4B
DELTA_QUAT_XOUT_H = 0x4C
DELTA_QUAT_YOUT_L = 0x4D
DELTA_QUAT_YOUT_H = 0x4E
DELTA_QUAT_ZOUT_L = 0x4F
DELTA_QUAT_ZOUT_H = 0x50
// Delta Velocity Outputs Register Adresses
DELTA_VEL_XOUT_L = 0x51
DELTA_VEL_XOUT_H = 0x52
DELTA_VEL_YOUT_L = 0x53
DELTA_VEL_YOUT_H = 0x54
DELTA_VEL_ZOUT_L = 0x55
DELTA_VEL_ZOUT_H = 0x56
)
+9 -3
View File
@@ -71,10 +71,13 @@ func (d *Driver) ConnectTCPSocket(addr, port string) error {
name[6] = byte(ipaddr[2])
name[7] = byte(ipaddr[3])
_, err = d.Rpc_lwip_connect(socket, name, uint32(len(name)))
result, err := d.Rpc_lwip_connect(socket, name, uint32(len(name)))
if err != nil {
return err
}
if result == -1 {
return fmt.Errorf("failed to connect to %d.%d.%d.%d port %s", addr[0], addr[1], addr[2], addr[3], port)
}
readset := []byte{}
writeset := []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
@@ -341,8 +344,11 @@ func (d *Driver) ReadSocket(b []byte) (n int, err error) {
if err != nil {
return 0, err
}
if nn < 0 {
return 0, fmt.Errorf("error %d", n)
if nn == -76 {
// no data
return 0, nil
} else if nn < 0 {
return 0, fmt.Errorf("error %d", nn)
} else if nn == 0 || nn == -30848 {
return 0, d.DisconnectSocket()
}
-1
View File
@@ -1,5 +1,4 @@
//go:build pybadge
// +build pybadge
package shifter
-1
View File
@@ -1,5 +1,4 @@
//go:build rp2040
// +build rp2040
package ssd1289
-1
View File
@@ -1,5 +1,4 @@
//go:build stm32wlx
// +build stm32wlx
package sx126x
+11 -4
View File
@@ -19,10 +19,11 @@ type DistanceMode uint8
type RangeStatus uint8
type rangingData struct {
mm uint16
status RangeStatus
signalRateMCPS int32 //MCPS : Mega Count Per Second
ambientRateMCPS int32
mm uint16
status RangeStatus
signalRateMCPS int32 //MCPS : Mega Count Per Second
ambientRateMCPS int32
effectiveSPADCount uint16
}
type resultBuffer struct {
@@ -337,6 +338,11 @@ func (d *Device) AmbientRate() int32 {
return d.rangingData.ambientRateMCPS
}
// EffectiveSPADCount returns the effective number of SPADs
func (d *Device) EffectiveSPADCount() uint16 {
return d.rangingData.effectiveSPADCount
}
// getRangingData stores in the buffer the ranging data
func (d *Device) getRangingData() {
d.rangingData.mm = uint16((uint32(d.results.mmCrosstalkSD0)*2011 + 0x0400) / 0x0800)
@@ -384,6 +390,7 @@ func (d *Device) getRangingData() {
d.rangingData.signalRateMCPS = 1000000 * int32(d.results.signalRateCrosstalkMCPSSD0) / (1 << 7)
d.rangingData.ambientRateMCPS = 1000000 * int32(d.results.ambientRateMCPSSD0) / (1 << 7)
d.rangingData.effectiveSPADCount = d.results.effectiveSPADCount
}
// setupManualCalibration configures the manual calibration
+323
View File
@@ -0,0 +1,323 @@
package wifinina
import (
"bufio"
"bytes"
"fmt"
"io"
"strconv"
"strings"
"time"
"tinygo.org/x/drivers/net/http"
)
func (d *Device) ListenAndServe(addr string, handler http.Handler) error {
if handler == nil {
handler = http.DefaultServeMux
}
server := newServer(d, handler)
if err := server.listen(addr); err != nil {
return err
}
for {
client, err := server.accept()
if err != nil {
return err
}
if err := client.handleHTTP(); err != nil {
return err
}
if err = client.stop(); err != nil {
return err
}
}
return nil
}
// Server stuff
type server struct {
device *Device
handler http.Handler
sock uint8
clients map[uint8]*client // keyed by client sock
}
func newServer(device *Device, handler http.Handler) *server {
return &server{
device: device,
handler: handler,
sock: NoSocketAvail,
clients: make(map[uint8]*client),
}
}
func portFromAddr(addr string) (uint16, error) {
// ignore anything before ':' in address
i := strings.LastIndex(addr, ":")
if i < 0 {
return 0, fmt.Errorf("Missing ':' in address")
}
v, err := strconv.ParseUint(addr[i+1:], 10, 16)
if err != nil {
return 0, fmt.Errorf("Parsing address err: %s", err)
}
return uint16(v), nil
}
func (s *server) listen(addr string) error {
port, err := portFromAddr(addr)
if err != nil {
return fmt.Errorf("Getting port err: %s", err)
}
s.sock, err = s.device.GetSocket()
if err != nil {
return fmt.Errorf("Getting socket err: %s", err)
}
if s.sock == NoSocketAvail {
return fmt.Errorf("No socket available")
}
return s.device.StartServer(port, s.sock, ProtoModeTCP)
}
func (s *server) availServer(sock uint8) (uint8, error) {
d := s.device
d.mu.Lock()
defer d.mu.Unlock()
if err := d.waitForChipSelect(); err != nil {
d.spiChipDeselect()
return NoSocketAvail, fmt.Errorf("Wait for CS: %s", err)
}
l := d.sendCmd(CmdAvailDataTCP, 1)
l += d.sendParam8(sock, true)
d.addPadding(l)
d.spiChipDeselect()
_, err := d.waitRspCmd1(CmdAvailDataTCP)
if err != nil {
return NoSocketAvail, fmt.Errorf("Wait for Rsp: %s", err)
}
newsock, err := d.getUint16(2, err)
if err != nil {
return NoSocketAvail, fmt.Errorf("getUint16: %s", err)
}
return uint8(newsock >> 8), nil
}
func (s *server) accept() (*client, error) {
for {
sock, err := s.availServer(s.sock)
if err != nil {
return nil, fmt.Errorf("accept: %w", err)
}
if sock == NoSocketAvail {
continue
}
if client, ok := s.clients[sock]; ok {
return client, nil
}
client := newClient(s, sock)
s.clients[sock] = client
return client, nil
}
}
// client stuff
type client struct {
server *server
device *Device
sock uint8
// HTTP request
req *http.Request
reqBuf bytes.Buffer
readBuf [256]byte
// HTTP response
res bytes.Buffer
resHdr http.Header
resBuf bytes.Buffer
statusCode int
}
func newClient(server *server, sock uint8) *client {
return &client{
server: server,
device: server.device,
sock: sock,
}
}
// client implements http.ResponseWriter interface
func (c *client) Header() http.Header {
return c.resHdr
}
func (c *client) Write(b []byte) (int, error) {
return c.resBuf.Write(b)
}
func (c *client) WriteHeader(statusCode int) {
c.statusCode = statusCode
}
func (c *client) status() uint8 {
d := c.device
d.mu.Lock()
defer d.mu.Unlock()
if err := d.waitForChipSelect(); err != nil {
d.spiChipDeselect()
return 0
}
l := d.sendCmd(CmdGetClientStateTCP, 1)
l += d.sendParam8(c.sock, true)
d.addPadding(l)
d.spiChipDeselect()
_, err := d.waitRspCmd1(CmdGetClientStateTCP)
if err != nil {
return 0
}
status, err := d.getUint8(1, err)
if err != nil {
return 0
}
return status
}
func (c *client) stop() error {
if err := c.device.StopClient(c.sock); err != nil {
return err
}
// Wait max 5 secs for the connection to close
for i := 0; i < 50 && c.status() != TCPStateClosed; i++ {
time.Sleep(100 * time.Millisecond)
}
if c.status() != TCPStateClosed {
return fmt.Errorf("stop failed, client status %x", c.status())
}
return nil
}
func (c *client) handleHTTP() error {
c.reqBuf.Reset()
end := -1
// read the request
start := time.Now()
for {
// TODO use Server.ReadTimeout
if time.Since(start) > 1*time.Second {
return fmt.Errorf("ReadTimeout")
}
n, err := c.device.GetDataBuf(c.sock, c.readBuf[:])
if err != nil {
return fmt.Errorf("GetDataBuf: %s", err)
}
if n == 0 {
time.Sleep(1 * time.Millisecond)
continue
}
c.reqBuf.Write(c.readBuf[:n])
bytesSoFar := c.reqBuf.Bytes()
if end == -1 {
// search for blank line marking end-of-header
end = bytes.Index(bytesSoFar, []byte("\r\n\r\n"))
if end == -1 {
continue
}
// found end-of-header; parse header
end += len([]byte("\r\n\r\n"))
bufio := bufio.NewReader(bytes.NewReader(bytesSoFar[:end]))
c.req, err = http.ReadRequest(bufio)
if err != nil {
return err
}
}
v := c.req.Header.Get("Content-Length")
if v == "" {
// no body; we're done reading request
break
}
length, _ := strconv.Atoi(v)
if end+length == len(bytesSoFar) {
// got the whole body
body := bytes.NewReader(bytesSoFar[end:])
c.req.Body = io.NopCloser(body)
break
}
// continue reading request...
}
// build the response
c.statusCode = 200
c.resHdr = http.Header{}
c.resHdr.Add(`Content-Type`, `text/html; charset=UTF-8`)
c.resHdr.Add(`Connection`, `close`)
c.resBuf.Reset()
c.server.handler.ServeHTTP(c, c.req)
c.resHdr.Add(`Content-Length`, fmt.Sprintf("%d", c.resBuf.Len()))
c.res.Reset()
fmt.Fprintf(&c.res, "HTTP/1.1 %d %s\r\n", c.statusCode,
http.StatusText(c.statusCode))
if err := c.resHdr.Write(&c.res); err != nil {
return err
}
c.res.WriteByte(byte('\n'))
c.res.Write(c.resBuf.Bytes())
// send the response
written, err := c.device.SendData(c.res.Bytes(), c.sock)
if err != nil {
return err
}
if written == 0 {
return ErrDataNotWritten
}
if sent, _ := c.device.CheckDataSent(c.sock); !sent {
return ErrCheckDataError
}
return nil
}
-2
View File
@@ -1,5 +1,4 @@
//go:build none
// +build none
package main
@@ -285,7 +284,6 @@ func main() {
}
defer f.Close()
fmt.Fprintln(f, "//go:build", architectures[*arch].buildTag)
fmt.Fprintln(f, "// +build", architectures[*arch].buildTag)
f.WriteString(`
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build cortexm
// +build cortexm
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo.riscv32
// +build tinygo.riscv32
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build avr
// +build avr
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build cortexm
// +build cortexm
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build !baremetal
// +build !baremetal
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo.riscv32
// +build tinygo.riscv32
package ws2812

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