Compare commits

...

12 Commits

Author SHA1 Message Date
Ron Evans c12f78eb50 Release: v0.9.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-12-23 17:09:00 +01:00
Daniel Esteban adb0c2c261 added generic 8bit shift register (#107)
* shifter: added generic 8bit shift register driver with ShiftPin Pin-compatible GPIO interface
2019-12-22 21:32:49 +01:00
Daniel Esteban 18f0722728 Dual stepper (#101)
* easystepper: added _DualDevice_ to move two motors at the same time
2019-12-22 10:33:02 +01:00
BCG e80a22d0ba Client driver for WiFiNINA firmware (#98)
* wifinina: implementation of WiFiNINA driver, including:
   - TCP client example is working
   - reading sockets and mqtt working
   - switched over to common net package also used by espat package
   - smoke tests and updated README for wifinina
2019-12-22 10:25:10 +01:00
BCG cc5ecafacf Decoupled net package from espat 2019-12-17 22:09:23 +01:00
Ayke van Laethem 7b56e61d52 ws2812: add support for simulation
Call a special __tinygo_ws2812_write_byte function to send a single
byte.
2019-12-14 22:16:41 +01:00
Ayke van Laethem 514b436889 ws2812: fix "invalid symbol redefinition" error
Named local labels shouldn't be used in LLVM because they might get
duplicated resulting in multiple symbol definitions and a compiler
error. Instead, use numeric labels.
2019-12-14 22:11:10 +01:00
BCG 7233452819 Added Feather M0 and Trinket M0 to build tags for WS2812 2019-12-12 14:28:21 +01:00
Ayke van Laethem 7929aa10ea all: add md5sum to smoke tests
This makes it easier to quickly compare all smoke tests for any changes.
2019-12-11 22:13:48 +01:00
Daniel Esteban 02084fd8a5 improvements in st7735/st7789 drivers 2019-12-08 16:38:05 +01:00
Jonathan Basseri f822da51fe Add support for Cortex-M4 120MHz
This adjusts the timing for 120MHz as seen on atsamd51 boards. The
timing was kept as close as possible to the Cortex-M4 64MHz logic in
ws2812_m4_64m.go.

Tested: This works on ItsyBitsy-M4
2019-12-06 11:33:55 +01:00
Jonathan Basseri c62d7db35d Fix number in comment
assembly comment was counting the # of nops.
2019-12-06 11:33:55 +01:00
36 changed files with 2538 additions and 143 deletions
+18
View File
@@ -1,3 +1,21 @@
0.9.0
---
- **new devices**
- net: shared implementation of net package for serial wifi devices
- shifter: add support for bit Parallel In Serial Out (PISO) shifter
- stepper: add support for dual stepper motor
- wifinina: add implementation for WiFiNINA firmware
- **enhancements**
- st7735: improvements in st7735 driver
- st7789: improvements in st7789 driver
- ws2812: add support for 120Mhz Cortex-M4
- ws2812: added Feather M0 and Trinket M0 to build tags for WS2812
- ws2812: add support for simulation
- **bugfixes**
- ws2812: fix "invalid symbol redefinition" error
- **examples**
- Add examples for wifinina drivers
0.8.0
---
- **new devices**
+92 -43
View File
@@ -9,48 +9,97 @@ fmt-check:
smoke-test:
@mkdir -p build
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/adxl345/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/apa102/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/at24cx/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/bh1750/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/blinkm/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/bmp180/main.go
tinygo build -size short -o ./build/test.elf -target=bluepill ./examples/ds1307/sram/main.go
tinygo build -size short -o ./build/test.elf -target=bluepill ./examples/ds1307/time/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/ds3231/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/easystepper/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/espat/espconsole/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/espat/esphub/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/espat/espstation/main.go
tinygo build -size short -o ./build/test.elf -target=feather-m0 ./examples/gps/i2c/main.go
tinygo build -size short -o ./build/test.elf -target=feather-m0 ./examples/gps/uart/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/hd44780/customchar/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/hd44780/text/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/hub75/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/lis3dh/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/lsm6ds3/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/mag3110/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/mcp3008/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/microbitmatrix/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/mma8653/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/mpu6050/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/pcd8544/setbuffer/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/pcd8544/setpixel/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/sht3x/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/ssd1306/i2c_128x32/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/ssd1306/spi_128x64/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/ssd1331/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/st7735/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/st7789/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/thermistor/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/vl53l1x/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/waveshare-epd/epd2in13/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/ws2812/main.go
tinygo build -size short -o ./build/test.elf -target=trinket-m0 ./examples/bme280/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/microphone/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/buzzer/main.go
tinygo build -size short -o ./build/test.elf -target=trinket-m0 ./examples/veml6070/main.go
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
@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=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
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espconsole/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/esphub/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espstation/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/customchar/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/text/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=circuitplay-express ./examples/lis3dh/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mag3110/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp3008/main.go
@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=itsybitsy-m0 ./examples/mma8653/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1331/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7735/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7789/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/thermistor/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl53l1x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/tcpclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/webclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bme280/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/microphone/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/buzzer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/veml6070/main.go
@md5sum ./build/test.hex
test: clean fmt-check smoke-test
+2
View File
@@ -67,6 +67,7 @@ The following 34 devices are supported.
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
| ["Easystepper" stepper motor controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
@@ -79,6 +80,7 @@ The following 34 devices are supported.
| [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 |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [Shift register](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |
+100 -18
View File
@@ -10,47 +10,117 @@ import (
type Device struct {
pins [4]machine.Pin
stepDelay int32
stepNumber int32
stepNumber uint8
}
// DualDevice holds information for controlling 2 motors
type DualDevice struct {
devices [2]Device
}
// New returns a new easystepper driver given 4 pins numbers (not pin object),
// number of steps and rpm
func New(pin1, pin2, pin3, pin4 machine.Pin, steps int32, rpm int32) Device {
pin1.Configure(machine.PinConfig{Mode: machine.PinOutput})
pin2.Configure(machine.PinConfig{Mode: machine.PinOutput})
pin3.Configure(machine.PinConfig{Mode: machine.PinOutput})
pin4.Configure(machine.PinConfig{Mode: machine.PinOutput})
return Device{
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
stepDelay: 60000000 / (steps * rpm),
}
}
// Configure configures the pins of the Device
func (d *Device) Configure() {
for _, pin := range d.pins {
pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
}
// NewDual returns a new dual easystepper driver given 8 pins numbers (not pin object),
// number of steps and rpm
func NewDual(pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8 machine.Pin, steps int32, rpm int32) DualDevice {
var dual DualDevice
dual.devices[0] = Device{
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
stepDelay: 60000000 / (steps * rpm),
}
dual.devices[1] = Device{
pins: [4]machine.Pin{pin5, pin6, pin7, pin8},
stepDelay: 60000000 / (steps * rpm),
}
return dual
}
// Configure configures the pins of the DualDevice
func (d *DualDevice) Configure() {
d.devices[0].Configure()
d.devices[1].Configure()
}
// Move rotates the motor the number of given steps
// (negative steps will rotate it the opposite direction)
func (d *Device) Move(steps int32) {
direction := steps > 0
if steps < 0 {
steps = -steps - d.stepNumber
} else {
steps += d.stepNumber
steps = -steps
}
var stepN int8
steps += int32(d.stepNumber)
var s int32
for s = d.stepNumber; s < steps; s++ {
d.stepMotor(d.stepNumber)
for s = int32(d.stepNumber); s < steps; s++ {
time.Sleep(time.Duration(d.stepDelay) * time.Microsecond)
if direction {
stepN = int8(s % 4)
} else {
stepN = int8((s + 2*(s%2)) % 4)
}
d.stepMotor(stepN)
d.moveDirectionSteps(direction, s)
}
d.stepNumber = int32(stepN)
}
// Off turns off all motor pins
func (d *Device) Off() {
for _, pin := range d.pins {
pin.Low()
}
}
// Move rotates the motors the number of given steps
// (negative steps will rotate it the opposite direction)
func (d *DualDevice) Move(stepsA, stepsB int32) {
min := uint8(1)
max := uint8(0)
var directions [2]bool
var minStep int32
directions[0] = stepsA > 0
directions[1] = stepsB > 0
if stepsA < 0 {
stepsA = -stepsA
}
if stepsB < 0 {
stepsB = -stepsB
}
if stepsB > stepsA {
stepsA, stepsB = stepsB, stepsA
max, min = min, max
}
d.devices[0].stepMotor(d.devices[0].stepNumber)
d.devices[1].stepMotor(d.devices[1].stepNumber)
stepsA += int32(d.devices[max].stepNumber)
minStep = int32(d.devices[min].stepNumber)
for s := int32(d.devices[max].stepNumber); s < stepsA; s++ {
time.Sleep(time.Duration(d.devices[0].stepDelay) * time.Microsecond)
d.devices[max].moveDirectionSteps(directions[max], s)
if ((s * stepsB) / stepsA) > minStep {
minStep++
d.devices[min].moveDirectionSteps(directions[min], minStep)
}
}
}
// Off turns off all motor pins
func (d *DualDevice) Off() {
d.devices[0].Off()
d.devices[1].Off()
}
// stepMotor changes the pins' state to the correct step
func (d *Device) stepMotor(step int8) {
func (d *Device) stepMotor(step uint8) {
switch step {
case 0:
d.pins[0].High()
@@ -77,4 +147,16 @@ func (d *Device) stepMotor(step int8) {
d.pins[3].High()
break
}
d.stepNumber = step
}
// moveDirectionSteps uses the direction to calculate the correct step and change the motor to it.
// Direction true: 0, 1, 2, 3, 0, 1, 2, ...
// Direction false: 0, 3, 2, 1, 0, 3, 2, ...
func (d *Device) moveDirectionSteps(direction bool, step int32) {
if direction {
d.stepMotor(uint8(step % 4))
} else {
d.stepMotor(uint8((step + 2*(step%2)) % 4))
}
}
+3
View File
@@ -24,6 +24,8 @@ import (
"strconv"
"strings"
"time"
"tinygo.org/x/drivers/net"
)
// Device wraps UART connection to the ESP8266/ESP32.
@@ -48,6 +50,7 @@ func New(b machine.UART) *Device {
// Configure sets up the device for communication.
func (d Device) Configure() {
ActiveDevice = &d
net.ActiveDevice = ActiveDevice
}
// Connected checks if there is communication with the ESP8266/ESP32.
+1
View File
@@ -9,6 +9,7 @@ import (
func main() {
motor := easystepper.New(machine.P13, machine.P15, machine.P14, machine.P16, 200, 75)
motor.Configure()
for {
println("CLOCKWISE")
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
"tinygo.org/x/drivers/net"
)
// change actAsAP to true to act as an access point instead of connecting to one.
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
"tinygo.org/x/drivers/net"
)
// access point info
+2 -2
View File
@@ -17,7 +17,7 @@ import (
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/mqtt"
"tinygo.org/x/drivers/net/mqtt"
)
// access point info
@@ -64,7 +64,7 @@ func main() {
return
}
opts := mqtt.NewClientOptions(adaptor)
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
+2 -2
View File
@@ -18,7 +18,7 @@ import (
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/mqtt"
"tinygo.org/x/drivers/net/mqtt"
)
// access point info
@@ -72,7 +72,7 @@ func main() {
return
}
opts := mqtt.NewClientOptions(adaptor)
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
"tinygo.org/x/drivers/net"
)
// access point info
+50
View File
@@ -0,0 +1,50 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/shifter"
)
func main() {
buttons := shifter.New(shifter.EIGHT_BITS, machine.BUTTON_LATCH, machine.BUTTON_CLK, machine.BUTTON_OUT)
buttons.Configure()
for {
// Slower
for i := 0; i < 8; i++ {
if buttons.Pins[i].Get() {
println("Button", i, "pressed")
}
}
// Faster
pressed, _ := buttons.Read8Input()
if pressed&machine.BUTTON_LEFT_MASK > 0 {
println("Button LEFT pressed")
}
if pressed&machine.BUTTON_UP_MASK > 0 {
println("Button UP pressed")
}
if pressed&machine.BUTTON_DOWN_MASK > 0 {
println("Button DOWN pressed")
}
if pressed&machine.BUTTON_RIGHT_MASK > 0 {
println("Button RIGHT pressed")
}
if pressed&machine.BUTTON_SELECT_MASK > 0 {
println("Button SELECT pressed")
}
if pressed&machine.BUTTON_START_MASK > 0 {
println("Button START pressed")
}
if pressed&machine.BUTTON_A_MASK > 0 {
println("Button A pressed")
}
if pressed&machine.BUTTON_B_MASK > 0 {
println("Button B pressed")
}
time.Sleep(100 * time.Millisecond)
}
}
+149
View File
@@ -0,0 +1,149 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
topic = "tinygo"
)
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
// Init esp8266/esp32
adaptor.Configure()
connectToAP()
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connectng to MQTT...")
cl := mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topic, 0, false, data)
token.Wait()
if err := token.Error(); err != nil {
switch t := err.(type) {
case wifinina.Error:
println(t.Error(), "attempting to reconnect")
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
default:
println(err.Error())
}
}
time.Sleep(1 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
time.Sleep(1 * time.Second)
}
println(ip.String())
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+162
View File
@@ -0,0 +1,162 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
cl mqtt.Client
topicTx = "tinygo/tx"
topicRx = "tinygo/rx"
)
func subHandler(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("[%s] ", msg.Topic())
fmt.Printf("%s\r\n", msg.Payload())
}
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
// Init esp8266/esp32
adaptor.Configure()
connectToAP()
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl = mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
// subscribe
token := cl.Subscribe(topicRx, 0, subHandler)
token.Wait()
if token.Error() != nil {
failMessage(token.Error().Error())
}
go publishing()
select {}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
func publishing() {
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topicRx, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(100 * time.Millisecond)
}
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
time.Sleep(1 * time.Second)
}
println(ip.String())
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+143
View File
@@ -0,0 +1,143 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends some data, for the purpose of testing speed and connectivity.
//
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
//
package main
import (
"bytes"
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the server aka "hub". Replace with your own info.
const serverIP = ""
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
)
var buf = &bytes.Buffer{}
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
adaptor.Configure()
connectToAP()
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
println("Done.")
}
func sendBatch() {
// make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
message("---------------\r\nDialing TCP connection")
conn, err := net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
message(err.Error())
time.Sleep(5 * time.Second)
}
n := 0
w := 0
start := time.Now()
// send data
message("Sending data")
for i := 0; i < 1000; i++ {
buf.Reset()
fmt.Fprint(buf,
"\r---------------------------- i == ", i, " ----------------------------"+
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
continue
}
n += w
}
buf.Reset()
ms := time.Now().Sub(start).Milliseconds()
fmt.Fprint(buf, "\nWrote ", n, " bytes in ", ms, " ms\r\n")
message(buf.String())
if _, err := conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message(ip.String())
}
func message(msg string) {
println(msg, "\r")
}
+153
View File
@@ -0,0 +1,153 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends a HTTP request to retrieve a webpage, based on the following
// Arduino example:
//
// https://github.com/arduino-libraries/WiFiNINA/blob/master/examples/WiFiWebClientRepeating/
//
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the server aka "hub". Replace with your own info.
const server = "tinygo.org"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
)
var buf [256]byte
var lastRequestTime time.Time
var conn net.Conn
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
adaptor.Configure()
connectToAP()
for {
loop()
}
println("Done.")
}
func loop() {
if conn != nil {
for n, err := conn.Read(buf[:]); n > 0; n, err = conn.Read(buf[:]) {
if err != nil {
println("Read error: " + err.Error())
} else {
print(string(buf[0:n]))
}
}
}
if time.Now().Sub(lastRequestTime).Milliseconds() >= 10000 {
makeHTTPRequest()
}
}
func makeHTTPRequest() {
var err error
if conn != nil {
conn.Close()
}
// make TCP connection
ip := net.ParseIP(server)
raddr := &net.TCPAddr{IP: ip, Port: 80}
laddr := &net.TCPAddr{Port: 8080}
message("\r\n---------------\r\nDialing TCP connection")
conn, err = net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
message("connection failed: " + err.Error())
time.Sleep(5 * time.Second)
}
println("Connected!\r")
print("Sending HTTP request...")
fmt.Fprintln(conn, "GET / HTTP/1.1")
fmt.Fprintln(conn, "Host:", server)
fmt.Fprintln(conn, "User-Agent: TinyGo/0.10.0")
fmt.Fprintln(conn, "Connection: close")
fmt.Fprintln(conn)
println("Sent!\r\n\r")
lastRequestTime = time.Now()
}
func readLine(conn *net.TCPSerialConn) string {
println("Attempting to read...\r")
b := buf[:]
for expiry := time.Now().Unix() + 10; time.Now().Unix() > expiry; {
if n, err := conn.Read(b); n > 0 && err == nil {
return string(b[0:n])
}
}
return ""
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message(ip.String())
}
func message(msg string) {
println(msg, "\r")
}
+27
View File
@@ -0,0 +1,27 @@
package net
type DeviceDriver interface {
GetDNS(domain string) (string, error)
ConnectTCPSocket(addr, port string) error
ConnectSSLSocket(addr, port string) error
ConnectUDPSocket(addr, sendport, listenport string) error
DisconnectSocket() error
StartSocketSend(size int) error
Write(b []byte) (n int, err error)
ReadSocket(b []byte) (n int, err error)
IsSocketDataAvailable() bool
// FIXME: this is really specific to espat, and maybe shouldn't be part
// of the driver interface
Response(timeout int) ([]byte, error)
}
var ActiveDevice DeviceDriver
func UseDriver(driver DeviceDriver) {
// TODO: rethink and refactor this
if ActiveDevice != nil {
panic("net.ActiveDevice is already set")
}
ActiveDevice = driver
}
+4 -5
View File
@@ -8,9 +8,8 @@ import (
"time"
"github.com/eclipse/paho.mqtt.golang/packets"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
"tinygo.org/x/drivers/espat/tls"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/tls"
)
// NewClient will create an MQTT v3.1.1 client with all of the options specified
@@ -24,7 +23,7 @@ func NewClient(o *ClientOptions) Client {
}
type mqttclient struct {
adaptor *espat.Device
adaptor net.DeviceDriver
conn net.Conn
connected bool
opts *ClientOptions
@@ -297,7 +296,7 @@ func (c *mqttclient) ackFunc(packet *packets.PublishPacket) func() {
// If there is no data yet but also is no error, it returns nil for both values.
func (c *mqttclient) ReadPacket() (packets.ControlPacket, error) {
// check for data first...
if espat.ActiveDevice.IsSocketDataAvailable() {
if net.ActiveDevice.IsSocketDataAvailable() {
return packets.ReadPacket(c.conn)
}
return nil, nil
+26 -4
View File
@@ -25,7 +25,7 @@ import (
"time"
"github.com/eclipse/paho.mqtt.golang/packets"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
const (
@@ -175,7 +175,7 @@ type ClientOptionsReader struct {
// ClientOptions contains configurable options for an MQTT Client.
type ClientOptions struct {
Adaptor *espat.Device
Adaptor net.DeviceDriver
//Servers []*url.URL
Servers string
@@ -209,8 +209,8 @@ type ClientOptions struct {
}
// NewClientOptions returns a new ClientOptions struct.
func NewClientOptions(adaptor *espat.Device) *ClientOptions {
return &ClientOptions{Adaptor: adaptor, ProtocolVersion: 4}
func NewClientOptions() *ClientOptions {
return &ClientOptions{Adaptor: net.ActiveDevice, ProtocolVersion: 4}
}
// AddBroker adds a broker URI to the list of brokers to be used. The format should be
@@ -256,3 +256,25 @@ func (o *ClientOptions) SetPassword(p string) *ClientOptions {
o.Password = p
return o
}
// SetWill accepts a string will message to be set. When the client connects,
// it will give this will message to the broker, which will then publish the
// provided payload (the will) to any clients that are subscribed to the provided
// topic.
func (o *ClientOptions) SetWill(topic string, payload string, qos byte, retained bool) *ClientOptions {
o.SetBinaryWill(topic, []byte(payload), qos, retained)
return o
}
// SetBinaryWill accepts a []byte will message to be set. When the client connects,
// it will give this will message to the broker, which will then publish the
// provided payload (the will) to any clients that are subscribed to the provided
// topic.
func (o *ClientOptions) SetBinaryWill(topic string, payload []byte, qos byte, retained bool) *ClientOptions {
o.WillEnabled = true
o.WillTopic = topic
o.WillPayload = payload
o.WillQos = qos
o.WillRetained = retained
return o
}
+13 -14
View File
@@ -7,8 +7,6 @@ import (
"strconv"
"strings"
"time"
"tinygo.org/x/drivers/espat"
)
// DialUDP makes a UDP network connection. raadr is the port that the messages will
@@ -20,15 +18,15 @@ func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPSerialConn, error) {
listenport := strconv.Itoa(laddr.Port)
// disconnect any old socket
espat.ActiveDevice.DisconnectSocket()
ActiveDevice.DisconnectSocket()
// connect new socket
err := espat.ActiveDevice.ConnectUDPSocket(addr, sendport, listenport)
err := ActiveDevice.ConnectUDPSocket(addr, sendport, listenport)
if err != nil {
return nil, err
}
return &UDPSerialConn{SerialConn: SerialConn{Adaptor: espat.ActiveDevice}, laddr: laddr, raddr: raddr}, nil
return &UDPSerialConn{SerialConn: SerialConn{Adaptor: ActiveDevice}, laddr: laddr, raddr: raddr}, nil
}
// ListenUDP listens for UDP connections on the port listed in laddr.
@@ -38,15 +36,15 @@ func ListenUDP(network string, laddr *UDPAddr) (*UDPSerialConn, error) {
listenport := strconv.Itoa(laddr.Port)
// disconnect any old socket
espat.ActiveDevice.DisconnectSocket()
ActiveDevice.DisconnectSocket()
// connect new socket
err := espat.ActiveDevice.ConnectUDPSocket(addr, sendport, listenport)
err := ActiveDevice.ConnectUDPSocket(addr, sendport, listenport)
if err != nil {
return nil, err
}
return &UDPSerialConn{SerialConn: SerialConn{Adaptor: espat.ActiveDevice}, laddr: laddr}, nil
return &UDPSerialConn{SerialConn: SerialConn{Adaptor: ActiveDevice}, laddr: laddr}, nil
}
// DialTCP makes a TCP network connection. raadr is the port that the messages will
@@ -57,15 +55,15 @@ func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPSerialConn, error) {
sendport := strconv.Itoa(raddr.Port)
// disconnect any old socket?
//espat.ActiveDevice.DisconnectSocket()
//ActiveDevice.DisconnectSocket()
// connect new socket
err := espat.ActiveDevice.ConnectTCPSocket(addr, sendport)
err := ActiveDevice.ConnectTCPSocket(addr, sendport)
if err != nil {
return nil, err
}
return &TCPSerialConn{SerialConn: SerialConn{Adaptor: espat.ActiveDevice}, laddr: laddr, raddr: raddr}, nil
return &TCPSerialConn{SerialConn: SerialConn{Adaptor: ActiveDevice}, laddr: laddr, raddr: raddr}, nil
}
// Dial connects to the address on the named network.
@@ -96,7 +94,7 @@ func Dial(network, address string) (Conn, error) {
// SerialConn is a loosely net.Conn compatible implementation
type SerialConn struct {
Adaptor *espat.Device
Adaptor DeviceDriver
}
// UDPSerialConn is a loosely net.Conn compatible intended to support
@@ -149,6 +147,7 @@ func (c *SerialConn) Write(b []byte) (n int, err error) {
if err != nil {
return n, err
}
/* TODO(bcg): this is kind of specific to espat, should maybe refactor */
_, err = c.Adaptor.Response(1000)
if err != nil {
return n, err
@@ -240,7 +239,7 @@ func ResolveTCPAddr(network, address string) (*TCPAddr, error) {
// TODO: make sure network is 'tcp'
// separate domain from port, if any
r := strings.Split(address, ":")
addr, err := espat.ActiveDevice.GetDNS(r[0])
addr, err := ActiveDevice.GetDNS(r[0])
if err != nil {
return nil, err
}
@@ -263,7 +262,7 @@ func ResolveUDPAddr(network, address string) (*UDPAddr, error) {
// TODO: make sure network is 'udp'
// separate domain from port, if any
r := strings.Split(address, ":")
addr, err := espat.ActiveDevice.GetDNS(r[0])
addr, err := ActiveDevice.GetDNS(r[0])
if err != nil {
return nil, err
}
+4 -5
View File
@@ -5,8 +5,7 @@ package tls
import (
"strconv"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
"tinygo.org/x/drivers/net"
)
// Dial makes a TLS network connection. It tries to provide a mostly compatible interface
@@ -22,15 +21,15 @@ func Dial(network, address string, config *Config) (*net.TCPSerialConn, error) {
sendport := strconv.Itoa(raddr.Port)
// disconnect any old socket
espat.ActiveDevice.DisconnectSocket()
net.ActiveDevice.DisconnectSocket()
// connect new socket
err = espat.ActiveDevice.ConnectSSLSocket(addr, sendport)
err = net.ActiveDevice.ConnectSSLSocket(addr, sendport)
if err != nil {
return nil, err
}
return net.NewTCPSerialConn(net.SerialConn{Adaptor: espat.ActiveDevice}, nil, raddr), nil
return net.NewTCPSerialConn(net.SerialConn{Adaptor: net.ActiveDevice}, nil, raddr), nil
}
// Config is a placeholder for future compatibility with
+104
View File
@@ -0,0 +1,104 @@
// Package shifter is for 8bit shift register, most common are 74HC165 and 74165
package shifter // import "tinygo.org/x/drivers/shifter"
import (
"errors"
"machine"
)
const (
EIGHT_BITS NumberBit = 8
SIXTEEN_BITS NumberBit = 16
THIRTYTWO_BITS NumberBit = 32
)
type NumberBit int8
// Device holds the Pins.
type Device struct {
latch machine.Pin
clk machine.Pin
out machine.Pin
Pins []ShiftPin
bits NumberBit
}
// ShiftPin is the implementation of the ShiftPin interface.
type ShiftPin struct {
pin machine.Pin
d *Device
}
// New returns a new thermistor driver given an ADC pin.
func New(numBits NumberBit, latch, clk, out machine.Pin) Device {
return Device{
latch: latch,
clk: clk,
out: out,
Pins: make([]ShiftPin, int(numBits)),
bits: numBits,
}
}
// Configure here just for interface compatibility.
func (d *Device) Configure() {
d.latch.Configure(machine.PinConfig{Mode: machine.PinOutput})
d.clk.Configure(machine.PinConfig{Mode: machine.PinOutput})
d.out.Configure(machine.PinConfig{Mode: machine.PinInput})
for i := 0; i < int(d.bits); i++ {
d.Pins[i] = d.GetShiftPin(i)
}
}
// GetShiftPin returns an ShiftPin for a specific input.
func (d *Device) GetShiftPin(input int) ShiftPin {
return ShiftPin{pin: machine.Pin(input), d: d}
}
// Read8Input reads the 8 inputs and return an uint8
func (d *Device) Read8Input() (uint8, error) {
if d.bits != EIGHT_BITS {
return 0, errors.New("wrong amount of registers")
}
return uint8(d.readInput(EIGHT_BITS)), nil
}
// Read16Input reads the 16 inputs and return an uint16
func (d *Device) Read16Input() (uint16, error) {
if d.bits != SIXTEEN_BITS {
return 0, errors.New("wrong amount of registers")
}
return uint16(d.readInput(SIXTEEN_BITS)), nil
}
// Read32Input reads the 32 inputs and return an uint32
func (d *Device) Read32Input() (uint32, error) {
if d.bits != THIRTYTWO_BITS {
return 0, errors.New("wrong amount of registers")
}
return d.readInput(THIRTYTWO_BITS), nil
}
// Get the current reading for a specific ShiftPin.
func (p ShiftPin) Get() bool {
return (p.d.readInput(p.d.bits) & (1 << int(p.pin))) > 0
}
// Configure here just for interface compatibility.
func (p ShiftPin) Configure() {
}
// readInput reads howMany bits from the shift register
func (d *Device) readInput(howMany NumberBit) uint32 {
d.latch.High()
var data uint32
for i := howMany - 1; i >= 0; i-- {
d.clk.Low()
if d.out.Get() {
data |= 1 << i
}
d.clk.High()
}
d.latch.Low()
return data
}
-20
View File
@@ -151,29 +151,9 @@ func (d *Device) Configure(cfg Config) {
if d.model == GREENTAB {
d.InvertColors(false)
d.Command(CASET)
d.Data(0x00)
d.Data(0x02)
d.Data(0x00)
d.Data(0x7F + 0x02)
d.Command(RASET)
d.Data(0x00)
d.Data(0x01)
d.Data(0x00)
d.Data(0x9F + 0x01)
} else if d.model == MINI80x160 {
d.isBGR = true
d.InvertColors(true)
d.Command(CASET)
d.Data(0x00)
d.Data(0x00)
d.Data(0x00)
d.Data(0x7F)
d.Command(RASET)
d.Data(0x00)
d.Data(0x00)
d.Data(0x00)
d.Data(0x9F)
}
// common color adjustment
-12
View File
@@ -100,18 +100,6 @@ func (d *Device) Configure(cfg Config) {
time.Sleep(10 * time.Millisecond)
d.SetRotation(d.rotation)
d.Command(CASET)
d.Data(0x00)
d.Data(uint8(d.columnOffset))
d.Data((240 + uint8(d.columnOffset)) >> 8)
d.Data(((240 + uint8(d.columnOffset)) >> 8) & 0xFF)
d.Command(RASET)
d.Data(0x00)
d.Data(uint8(d.rowOffset))
d.Data((240 + uint8(d.rowOffset)) >> 8)
d.Data(((240 + uint8(d.rowOffset)) >> 8) & 0xFF)
d.InvertColors(true)
d.Command(NORON)
+1 -1
View File
@@ -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.8.0"
const Version = "0.9.0"
+3
View File
@@ -0,0 +1,3 @@
WiFiNINA protocol
=================
+213
View File
@@ -0,0 +1,213 @@
package wifinina
import (
"fmt"
"strconv"
"time"
"tinygo.org/x/drivers/net"
)
const (
ReadBufferSize = 128
)
func (d *Device) NewDriver() net.DeviceDriver {
return &Driver{dev: d, sock: NoSocketAvail}
}
type Driver struct {
dev *Device
sock uint8
readBuf readBuffer
}
type readBuffer struct {
data [ReadBufferSize]byte
head int
size int
}
func (drv *Driver) GetDNS(domain string) (string, error) {
ipAddr, err := drv.dev.GetHostByName(domain)
return ipAddr.String(), err
}
func (drv *Driver) ConnectTCPSocket(addr, portStr string) error {
return drv.connectSocket(addr, portStr, ProtoModeTCP)
}
func (drv *Driver) ConnectSSLSocket(addr, portStr string) error {
return drv.connectSocket(addr, portStr, ProtoModeTLS)
}
func (drv *Driver) connectSocket(addr, portStr string, mode uint8) error {
// convert port to uint16
p64, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
return fmt.Errorf("could not convert port to uint16: %s", err.Error())
}
port := uint16(p64)
// look up the hostname if necessary; if an IP address was specified, the
// same will be returned. Otherwise, an IPv4 for the hostname is returned.
ipAddr, err := drv.dev.GetHostByName(addr)
if err != nil {
return err
}
ip := ipAddr.AsUint32()
// check to see if socket is already set; if so, stop it
if drv.sock != NoSocketAvail {
if err := drv.stop(); err != nil {
return err
}
}
// get a socket from the device
if drv.sock, err = drv.dev.GetSocket(); err != nil {
return err
}
// attempt to start the client
if err := drv.dev.StartClient(ip, port, drv.sock, mode); err != nil {
return err
}
// FIXME: this 4 second timeout is simply mimicking the Arduino driver
for t := newTimer(4 * time.Second); !t.Expired(); {
connected, err := drv.IsConnected()
if err != nil {
return err
}
if connected {
return nil
}
wait(1 * time.Millisecond)
}
return ErrConnectionTimeout
}
func (drv *Driver) ConnectUDPSocket(addr, sport, lport string) error {
return ErrNotImplemented
}
func (drv *Driver) DisconnectSocket() error {
return drv.stop()
}
func (drv *Driver) StartSocketSend(size int) error {
// not needed for WiFiNINA???
return nil
}
func (drv *Driver) Response(timeout int) ([]byte, error) {
return nil, nil
}
func (drv *Driver) Write(b []byte) (n int, err error) {
if drv.sock == NoSocketAvail {
return 0, ErrNoSocketAvail
}
if len(b) == 0 {
return 0, ErrNoData
}
written, err := drv.dev.SendData(b, drv.sock)
if err != nil {
return 0, err
}
if written == 0 {
return 0, ErrDataNotWritten
}
if sent, _ := drv.dev.CheckDataSent(drv.sock); !sent {
return 0, ErrCheckDataError
}
return len(b), nil
}
func (drv *Driver) ReadSocket(b []byte) (n int, err error) {
avail, err := drv.available()
if err != nil {
println("ReadSocket error: " + err.Error())
return 0, err
}
if avail == 0 {
return 0, nil
}
length := len(b)
if avail < length {
length = avail
}
copy(b, drv.readBuf.data[drv.readBuf.head:drv.readBuf.head+length])
drv.readBuf.head += length
drv.readBuf.size -= length
return length, nil
}
// IsSocketDataAvailable returns of there is socket data available
func (drv *Driver) IsSocketDataAvailable() bool {
n, err := drv.available()
return err == nil && n > 0
}
func (drv *Driver) available() (int, error) {
if drv.readBuf.size == 0 {
n, err := drv.dev.GetDataBuf(drv.sock, drv.readBuf.data[:])
if n > 0 {
drv.readBuf.head = 0
drv.readBuf.size = n
}
if err != nil {
return int(n), err
}
}
return drv.readBuf.size, nil
}
func (drv *Driver) IsConnected() (bool, error) {
if drv.sock == NoSocketAvail {
return false, nil
}
s, err := drv.status()
if err != nil {
return false, err
}
isConnected := !(s == TCPStateListen || s == TCPStateClosed ||
s == TCPStateFinWait1 || s == TCPStateFinWait2 || s == TCPStateTimeWait ||
s == TCPStateSynSent || s == TCPStateSynRcvd || s == TCPStateCloseWait)
// TODO: investigate if the below is necessary (as per Arduino driver)
//if !isConnected {
// //close socket buffer?
// WiFiSocketBuffer.close(_sock);
// _sock = 255;
//}
return isConnected, nil
}
func (drv *Driver) status() (uint8, error) {
if drv.sock == NoSocketAvail {
return TCPStateClosed, nil
}
return drv.dev.GetClientState(drv.sock)
}
func (drv *Driver) stop() error {
if drv.sock == NoSocketAvail {
return nil
}
drv.dev.StopClient(drv.sock)
for t := newTimer(5 * time.Second); !t.Expired(); {
st, _ := drv.status()
if st == TCPStateClosed {
break
}
// FIXME: without the time.Sleep below this blocks until TCPStateClosed,
// however with it got goroutine stack overflows; not sure if this is still
// an issue so should investigate further
//time.Sleep(1 * time.Millisecond)
}
drv.sock = NoSocketAvail
return nil
}
+28
View File
@@ -0,0 +1,28 @@
package wifinina
import "time"
func wait(duration time.Duration) {
newTimer(duration).WaitUntilExpired()
}
type timer struct {
start int64
interval int64
}
func newTimer(interval time.Duration) timer {
return timer{
start: time.Now().UnixNano(),
interval: int64(interval),
}
}
func (t timer) Expired() bool {
return time.Now().UnixNano() > (t.start + t.interval)
}
func (t timer) WaitUntilExpired() {
for !t.Expired() {
}
}
+1032
View File
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
// +build !baremetal
package ws2812
// This file implements the WS2812 protocol for simulation.
import "machine"
// Send a single byte using the WS2812 protocol.
func (d Device) WriteByte(c byte) error {
writeByte(d.Pin, c)
return nil
}
//go:export __tinygo_ws2812_write_byte
func writeByte(pin machine.Pin, c byte)
+4 -4
View File
@@ -24,13 +24,13 @@ func (d Device) WriteByte(c byte) error {
// T1H: 8 cycles or 500.0ns -> together 19 cycles or 1187.5ns
value := uint32(c) << 24
arm.AsmFull(`
send_bit:
1: @ send_bit
str {maskSet}, {portSet} @ [2] T0H and T0L start here
nop @ [1]
lsls {value}, #1 @ [1]
bcs.n skip_store @ [1/3]
bcs.n 2f @ [1/3] skip_store
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
skip_store:
2: @ skip_store
nop @ [4]
nop
nop
@@ -39,7 +39,7 @@ func (d Device) WriteByte(c byte) error {
nop @ [2]
nop
subs {i}, #1 @ [1]
bne.n send_bit @ [1/3]
bne.n 1b @ [1/3] send_bit
`, map[string]interface{}{
"value": value,
"i": 8,
+5 -5
View File
@@ -1,4 +1,4 @@
// +build circuitplay_express itsybitsy_m0 arduino_nano33
// +build atsamd21
package ws2812
@@ -23,7 +23,7 @@ func (d Device) WriteByte(c byte) error {
// T1L: 22 cycles or 458.3ns -> together 49 cycles or 1020.8ns
value := uint32(c) << 24
arm.AsmFull(`
send_bit:
1: @ send_bit
str {maskSet}, {portSet} @ [2] T0H and T0L start here
lsls {value}, #1 @ [1]
nop @ [6]
@@ -32,9 +32,9 @@ func (d Device) WriteByte(c byte) error {
nop
nop
nop
bcs.n skip_store @ [1/3]
bcs.n 2f @ [1/3] skip_store
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
skip_store:
2: @ skip_store
nop @ [15]
nop
nop
@@ -68,7 +68,7 @@ func (d Device) WriteByte(c byte) error {
nop
nop
subs {i}, #1 @ [1]
bne.n send_bit @ [1/3]
bne.n 1b @ [1/3] send_bit
`, map[string]interface{}{
"value": value,
"i": 8,
+173
View File
@@ -0,0 +1,173 @@
// +build atsamd51
package ws2812
// This file implements the WS2812 protocol for 120MHz Cortex-M4
// microcontrollers.
// Note: This implementation does not work with tinygo 0.9.0 or older.
import (
"device/arm"
)
// Send a single byte using the WS2812 protocol.
func (d Device) WriteByte(c byte) error {
// For the Cortex-M4 at 120MHz
portSet, maskSet := d.Pin.PortMaskSet()
portClear, maskClear := d.Pin.PortMaskClear()
// See:
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
// T0H: 32-34 cycles or 266.67ns - 283.33ns
// T0L: 101-103 cycles or 841.67ns - 858.33ns
// +: 133-137 cycles or 1108.33ns - 1141.67ns
// T1H: 73-75 cycles or 608.33ns - 625.00ns
// T1L: 58-60 cycles or 483.33ns - 500.00ns
// +: 131-135 cycles or 1091.67ns - 1125.00ns
// A branch is treated here as 1-3 cycles, because apparently it might get
// speculated. This is more of a guess than hard fact, because the only docs
// by ARM that state this are now considered superseded (by what?).
value := uint32(c) << 24
arm.AsmFull(`
1: @ send_bit
str {maskSet}, {portSet} @ [2] T0H and T0L start here
lsls {value}, #1 @ [1]
nop @ [28]
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
bcs.n 2f @ [1-3] skip_store
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
2: @ skip_store
nop @ [41]
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
str {maskClear}, {portClear} @ [2] T1H -> T1L transition
nop @ [54]
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
subs {i}, #1 @ [1]
bne.n 1b @ [1-3] send_bit
`, map[string]interface{}{
"value": value,
"i": 8,
"maskSet": maskSet,
"portSet": portSet,
"maskClear": maskClear,
"portClear": portClear,
})
return nil
}
+5 -5
View File
@@ -28,10 +28,10 @@ func (d Device) WriteByte(c byte) error {
// by ARM that state this are now considered superseded (by what?).
value := uint32(c) << 24
arm.AsmFull(`
send_bit:
1: @ send_bit
str {maskSet}, {portSet} @ [2] T0H and T0L start here
lsls {value}, #1 @ [1]
nop @ [10]
nop @ [13]
nop
nop
nop
@@ -44,9 +44,9 @@ func (d Device) WriteByte(c byte) error {
nop
nop
nop
bcs.n skip_store @ [1-3]
bcs.n 2f @ [1-3] skip_store
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
skip_store:
2: @ skip_store
nop @ [22]
nop
nop
@@ -97,7 +97,7 @@ func (d Device) WriteByte(c byte) error {
nop
nop
subs {i}, #1 @ [1]
bne.n send_bit @ [1-3]
bne.n 1b @ [1-3] send_bit
`, map[string]interface{}{
"value": value,
"i": 8,