mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-30 20:47:49 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cbf1a6f3d | |||
| 001bdb43ba | |||
| f7ae6fac6d | |||
| a575b2a4ed | |||
| 0bc3702dd0 | |||
| b53a8a17e7 | |||
| 5e117c162c | |||
| 24dfd8795a | |||
| a748451cab | |||
| a811483fd4 | |||
| 7b565e8cb0 | |||
| 5645eb3f91 | |||
| 6b914f7af7 | |||
| 5a02fe068b | |||
| 5ecefde991 | |||
| 9adbde99a2 | |||
| a09ec31e7a | |||
| d07ad40373 | |||
| aa17ffd1cb |
@@ -1,3 +1,28 @@
|
||||
0.17.1
|
||||
---
|
||||
- To correct an error in the release process. Same as 0.17.0.
|
||||
|
||||
0.17.0
|
||||
---
|
||||
- **new devices**
|
||||
- rtl8720dn: add support for rtl8720dn
|
||||
- sdcard: add support for spi sdcard driver, along with fatfs
|
||||
- **enhancements**
|
||||
- apa102: use 4-byte buffer to improve speed
|
||||
- bmi160: avoid heap allocations
|
||||
- ili9341: add standard SPI driver
|
||||
- wifinina
|
||||
- avoid fmt package
|
||||
- Fix RSSI command for WiFiNINA + Print current SSID + Wait for correct time before printing it out + Cleanup
|
||||
- ws2812
|
||||
- rename the pin to ws2812
|
||||
- add tag for nrf52833
|
||||
- Disable interrupts before sending ws2812 data
|
||||
- add support for qtpy and atsame5x
|
||||
- **core**
|
||||
- modules: switch to use tinygo-org version of tinyfs package
|
||||
- all: use machine.Serial as the default output
|
||||
|
||||
0.16.0
|
||||
---
|
||||
- **new devices**
|
||||
|
||||
@@ -193,12 +193,18 @@ endif
|
||||
@md5sum ./build/test.hex
|
||||
tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
|
||||
@md5sum ./build/test.hex
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/
|
||||
@md5sum ./build/test.hex
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/tinyfs/
|
||||
@md5sum ./build/test.hex
|
||||
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webclient/
|
||||
@md5sum ./build/test.hex
|
||||
|
||||
DRIVERS = $(wildcard */)
|
||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
|
||||
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \
|
||||
pcf8563 mcp2515 servo
|
||||
pcf8563 mcp2515 servo sdcard rtl8720dn
|
||||
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
||||
|
||||
unit-test:
|
||||
|
||||
@@ -52,7 +52,7 @@ func main() {
|
||||
|
||||
## Currently supported devices
|
||||
|
||||
The following 65 devices are supported.
|
||||
The following 67 devices are supported.
|
||||
|
||||
| Device Name | Interface Type |
|
||||
|----------|-------------|
|
||||
@@ -100,12 +100,14 @@ The following 65 devices are supported.
|
||||
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
|
||||
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
|
||||
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
|
||||
| [RTL8720DN 2.4G/5G Dual Bands Wireless and BLE5.0](https://www.seeedstudio.com/Realtek8720DN-2-4G-5G-Dual-Bands-Wireless-and-BLE5-0-Combo-Module-p-4442.html) | UART |
|
||||
| [Semihosting](https://wiki.segger.com/Semihosting) | Debug |
|
||||
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
|
||||
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
|
||||
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
|
||||
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
|
||||
| [SPI NOR Flash Memory](https://en.wikipedia.org/wiki/Flash_memory#NOR_flash) | SPI/QSPI |
|
||||
| [SPI SDCARD/MMC](https://en.wikipedia.org/wiki/SD_card) | SPI |
|
||||
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
|
||||
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |
|
||||
| [SSD1351 OLED display](https://download.mikroe.com/documents/datasheets/ssd1351-revision-1.3.pdf) | SPI |
|
||||
|
||||
+19
-17
@@ -27,44 +27,46 @@ var startFrame = []byte{0x00, 0x00, 0x00, 0x00}
|
||||
type Device struct {
|
||||
bus drivers.SPI
|
||||
Order int
|
||||
buf [4]byte
|
||||
}
|
||||
|
||||
// New returns a new APA102 driver. Pass in a fully configured SPI bus.
|
||||
func New(b drivers.SPI) Device {
|
||||
return Device{bus: b, Order: BGR}
|
||||
func New(b drivers.SPI) *Device {
|
||||
return &Device{bus: b, Order: BGR}
|
||||
}
|
||||
|
||||
// NewSoftwareSPI returns a new APA102 driver that will use a software based
|
||||
// implementation of the SPI protocol.
|
||||
func NewSoftwareSPI(sckPin, sdoPin machine.Pin, delay uint32) Device {
|
||||
func NewSoftwareSPI(sckPin, sdoPin machine.Pin, delay uint32) *Device {
|
||||
return New(&bbSPI{SCK: sckPin, SDO: sdoPin, Delay: delay})
|
||||
}
|
||||
|
||||
// WriteColors writes the given RGBA color slice out using the APA102 protocol.
|
||||
// The A value (Alpha channel) is used for brightness, set to 0xff (255) for maximum.
|
||||
func (d Device) WriteColors(cs []color.RGBA) (n int, err error) {
|
||||
func (d *Device) WriteColors(cs []color.RGBA) (n int, err error) {
|
||||
d.startFrame()
|
||||
|
||||
// write data
|
||||
for _, c := range cs {
|
||||
// brightness is scaled to 5 bit value
|
||||
d.bus.Transfer(0xe0 | (c.A >> 3))
|
||||
d.buf[0] = 0xe0 | (c.A >> 3)
|
||||
|
||||
// set the colors
|
||||
switch d.Order {
|
||||
case BRG:
|
||||
d.bus.Transfer(c.B)
|
||||
d.bus.Transfer(c.R)
|
||||
d.bus.Transfer(c.G)
|
||||
d.buf[1] = c.B
|
||||
d.buf[2] = c.R
|
||||
d.buf[3] = c.G
|
||||
case GRB:
|
||||
d.bus.Transfer(c.G)
|
||||
d.bus.Transfer(c.R)
|
||||
d.bus.Transfer(c.B)
|
||||
d.buf[1] = c.G
|
||||
d.buf[2] = c.R
|
||||
d.buf[3] = c.B
|
||||
case BGR:
|
||||
d.bus.Transfer(c.B)
|
||||
d.bus.Transfer(c.G)
|
||||
d.bus.Transfer(c.R)
|
||||
d.buf[1] = c.B
|
||||
d.buf[2] = c.G
|
||||
d.buf[3] = c.R
|
||||
}
|
||||
d.bus.Tx(d.buf[:], nil)
|
||||
}
|
||||
|
||||
d.endFrame(len(cs))
|
||||
@@ -73,7 +75,7 @@ func (d Device) WriteColors(cs []color.RGBA) (n int, err error) {
|
||||
}
|
||||
|
||||
// Write the raw bytes using the APA102 protocol.
|
||||
func (d Device) Write(buf []byte) (n int, err error) {
|
||||
func (d *Device) Write(buf []byte) (n int, err error) {
|
||||
d.startFrame()
|
||||
d.bus.Tx(buf, nil)
|
||||
d.endFrame(len(buf) / 4)
|
||||
@@ -82,14 +84,14 @@ func (d Device) Write(buf []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
// startFrame sends the start bytes for a strand of LEDs.
|
||||
func (d Device) startFrame() {
|
||||
func (d *Device) startFrame() {
|
||||
d.bus.Tx(startFrame, nil)
|
||||
}
|
||||
|
||||
// endFrame sends the end frame marker with one extra bit per LED so
|
||||
// long strands of LEDs receive the necessary termination for updates.
|
||||
// See https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
|
||||
func (d Device) endFrame(count int) {
|
||||
func (d *Device) endFrame(count int) {
|
||||
for i := 0; i < count/16; i++ {
|
||||
d.bus.Transfer(0xff)
|
||||
}
|
||||
|
||||
+24
-5
@@ -13,6 +13,8 @@ type DeviceSPI struct {
|
||||
// Chip select pin
|
||||
CSB machine.Pin
|
||||
|
||||
buf [7]byte
|
||||
|
||||
// SPI bus (requires chip select to be usable).
|
||||
Bus drivers.SPI
|
||||
}
|
||||
@@ -80,7 +82,10 @@ func (d *DeviceSPI) Reset() error {
|
||||
|
||||
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
|
||||
func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
|
||||
data := []byte{0x80 | reg_TEMPERATURE_0, 0, 0}
|
||||
data := d.buf[:3]
|
||||
data[0] = 0x80 | reg_TEMPERATURE_0
|
||||
data[1] = 0
|
||||
data[2] = 0
|
||||
d.CSB.Low()
|
||||
err = d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
@@ -113,7 +118,11 @@ func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) {
|
||||
// and the sensor is not moving the returned value will be around 1000000 or
|
||||
// -1000000.
|
||||
func (d *DeviceSPI) ReadAcceleration() (x int32, y int32, z int32, err error) {
|
||||
data := []byte{0x80 | reg_ACC_XL, 0, 0, 0, 0, 0, 0}
|
||||
data := d.buf[:7]
|
||||
data[0] = 0x80 | reg_ACC_XL
|
||||
for i := 1; i < len(data); i++ {
|
||||
data[i] = 0
|
||||
}
|
||||
d.CSB.Low()
|
||||
err = d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
@@ -139,7 +148,11 @@ func (d *DeviceSPI) ReadAcceleration() (x int32, y int32, z int32, err error) {
|
||||
// rotation along one axis and while doing so integrate all values over time,
|
||||
// you would get a value close to 360000000.
|
||||
func (d *DeviceSPI) ReadRotation() (x int32, y int32, z int32, err error) {
|
||||
data := []byte{0x80 | reg_GYR_XL, 0, 0, 0, 0, 0, 0}
|
||||
data := d.buf[:7]
|
||||
data[0] = 0x80 | reg_GYR_XL
|
||||
for i := 1; i < len(data); i++ {
|
||||
data[i] = 0
|
||||
}
|
||||
d.CSB.Low()
|
||||
err = d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
@@ -185,7 +198,9 @@ func (d *DeviceSPI) readRegister(address uint8) uint8 {
|
||||
// I don't know why but it appears necessary to sleep for a bit here.
|
||||
time.Sleep(time.Millisecond)
|
||||
|
||||
data := []byte{0x80 | address, 0}
|
||||
data := d.buf[:2]
|
||||
data[0] = 0x80 | address
|
||||
data[1] = 0
|
||||
d.CSB.Low()
|
||||
d.Bus.Tx(data, data)
|
||||
d.CSB.High()
|
||||
@@ -198,7 +213,11 @@ func (d *DeviceSPI) writeRegister(address, data uint8) {
|
||||
// I don't know why but it appears necessary to sleep for a bit here.
|
||||
time.Sleep(time.Millisecond)
|
||||
|
||||
buf := d.buf[:2]
|
||||
buf[0] = address
|
||||
buf[1] = data
|
||||
|
||||
d.CSB.Low()
|
||||
d.Bus.Tx([]byte{address, data}, []byte{0, 0})
|
||||
d.Bus.Tx(buf, buf)
|
||||
d.CSB.High()
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
apa apa102.Device
|
||||
apa *apa102.Device
|
||||
|
||||
pwm = machine.TCC0
|
||||
leds = make([]color.RGBA, 1)
|
||||
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
tx = machine.PA22
|
||||
rx = machine.PA23
|
||||
|
||||
console = machine.UART0
|
||||
console = machine.Serial
|
||||
|
||||
adaptor *espat.Device
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ var (
|
||||
tx = machine.PA22
|
||||
rx = machine.PA23
|
||||
|
||||
console = machine.UART0
|
||||
console = machine.Serial
|
||||
|
||||
adaptor *espat.Device
|
||||
topic = "tinygo"
|
||||
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
tx = machine.PA22
|
||||
rx = machine.PA23
|
||||
|
||||
console = machine.UART0
|
||||
console = machine.Serial
|
||||
|
||||
adaptor *espat.Device
|
||||
cl mqtt.Client
|
||||
|
||||
@@ -20,7 +20,7 @@ var (
|
||||
input [consoleBufLen]byte
|
||||
store [storageBufLen]byte
|
||||
|
||||
console = machine.UART0
|
||||
console = machine.Serial
|
||||
|
||||
dev *flash.Device
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func main() {
|
||||
println("GPS UART Example")
|
||||
machine.UART1.Configure(machine.UARTConfig{BaudRate: 9600})
|
||||
ublox := gps.NewUART(&machine.UART1)
|
||||
ublox := gps.NewUART(machine.UART1)
|
||||
parser := gps.NewParser()
|
||||
var fix gps.Fix
|
||||
for {
|
||||
|
||||
@@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
frameBuffer = [(graphics.BALLHEIGHT + 8) * (graphics.BALLWIDTH + 8)]uint16{}
|
||||
frameBuffer = [(graphics.BALLHEIGHT + 8) * (graphics.BALLWIDTH + 8) * 2]uint8{}
|
||||
|
||||
startTime int64
|
||||
frame int64
|
||||
@@ -179,7 +179,8 @@ func main() {
|
||||
c = BGCOLOR
|
||||
}
|
||||
}
|
||||
frameBuffer[y*int(width)+x] = c
|
||||
frameBuffer[(y*int(width)+x)*2] = byte(c >> 8)
|
||||
frameBuffer[(y*int(width)+x)*2+1] = byte(c)
|
||||
bx1++ // Increment bitmap position counters (X axis)
|
||||
bgx1++
|
||||
}
|
||||
@@ -190,7 +191,7 @@ func main() {
|
||||
bgy++
|
||||
}
|
||||
|
||||
display.DrawRGBBitmap(minx, miny, frameBuffer[:width*height], width, height)
|
||||
display.DrawRGBBitmap8(minx, miny, frameBuffer[:width*height*2], width, height)
|
||||
|
||||
// Show approximate frame rate
|
||||
frame++
|
||||
@@ -215,11 +216,13 @@ func DrawBackground() {
|
||||
b = graphics.Background[j*byteWidth+k/8]
|
||||
}
|
||||
if b&0x80 == 0 {
|
||||
frameBuffer[k] = BGCOLOR
|
||||
frameBuffer[2*k] = byte(BGCOLOR >> 8)
|
||||
frameBuffer[2*k+1] = byte(BGCOLOR & 0xFF)
|
||||
} else {
|
||||
frameBuffer[k] = GRIDCOLOR
|
||||
frameBuffer[2*k] = byte(GRIDCOLOR >> 8)
|
||||
frameBuffer[2*k+1] = byte(GRIDCOLOR & 0xFF)
|
||||
}
|
||||
}
|
||||
display.DrawRGBBitmap(0, j, frameBuffer[0:w], w, 1)
|
||||
display.DrawRGBBitmap8(0, j, frameBuffer[0:w*2], w, 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/net"
|
||||
"tinygo.org/x/drivers/net/tls"
|
||||
"tinygo.org/x/drivers/rtl8720dn"
|
||||
)
|
||||
|
||||
// You can override the setting with the init() in another source code.
|
||||
// func init() {
|
||||
// ssid = "your-ssid"
|
||||
// password = "your-password"
|
||||
// debug = true
|
||||
// server = "tinygo.org"
|
||||
// test_root_ca = "..."
|
||||
// }
|
||||
|
||||
var (
|
||||
ssid string
|
||||
password string
|
||||
server string = "www.example.com"
|
||||
debug = false
|
||||
)
|
||||
|
||||
// Set the test_root_ca created by the following command
|
||||
// $ openssl s_client -showcerts -verify 5 -connect www.example.com:443 < /dev/null
|
||||
var test_root_ca = `-----BEGIN CERTIFICATE-----
|
||||
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
var buf [0x400]byte
|
||||
|
||||
var lastRequestTime time.Time
|
||||
var conn net.Conn
|
||||
var adaptor *rtl8720dn.RTL8720DN
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
for err != nil {
|
||||
fmt.Printf("error: %s\r\n", err.Error())
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
rtl, err := setupRTL8720DN()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rtl.SetRootCA(&test_root_ca)
|
||||
net.UseDriver(rtl)
|
||||
|
||||
err = rtl.ConnectToAP(ssid, password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ip, subnet, gateway, err := rtl.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)
|
||||
|
||||
cnt := 0
|
||||
for {
|
||||
readConnection()
|
||||
if time.Now().Sub(lastRequestTime).Milliseconds() >= 10000 {
|
||||
makeHTTPSRequest()
|
||||
cnt++
|
||||
fmt.Printf("-------- %d --------\r\n", cnt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readConnection() {
|
||||
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]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeHTTPSRequest() {
|
||||
|
||||
var err error
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
message("\r\n---------------\r\nDialing TCP connection")
|
||||
conn, err = tls.Dial("tcp", server, nil)
|
||||
for ; err != nil; conn, err = tls.Dial("tcp", server, nil) {
|
||||
message("Connection failed: " + err.Error())
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
println("Connected!\r")
|
||||
|
||||
print("Sending HTTPS request...")
|
||||
fmt.Fprintln(conn, "GET / HTTP/1.1")
|
||||
fmt.Fprintln(conn, "Host:", strings.Split(server, ":")[0])
|
||||
fmt.Fprintln(conn, "User-Agent: TinyGo")
|
||||
fmt.Fprintln(conn, "Connection: close")
|
||||
fmt.Fprintln(conn)
|
||||
println("Sent!\r\n\r")
|
||||
|
||||
lastRequestTime = time.Now()
|
||||
}
|
||||
|
||||
func message(msg string) {
|
||||
println(msg, "\r")
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// +build wioterminal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"device/sam"
|
||||
"machine"
|
||||
"runtime/interrupt"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/rtl8720dn"
|
||||
)
|
||||
|
||||
var (
|
||||
uart UARTx
|
||||
)
|
||||
|
||||
func handleInterrupt(interrupt.Interrupt) {
|
||||
// should reset IRQ
|
||||
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
|
||||
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
|
||||
}
|
||||
|
||||
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
|
||||
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
machine.RTL8720D_CHIP_PU.Low()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
machine.RTL8720D_CHIP_PU.High()
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
waitSerial()
|
||||
|
||||
uart = UARTx{
|
||||
UART: &machine.UART{
|
||||
Buffer: machine.NewRingBuffer(),
|
||||
Bus: sam.SERCOM0_USART_INT,
|
||||
SERCOM: 0,
|
||||
},
|
||||
}
|
||||
|
||||
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
|
||||
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
|
||||
|
||||
rtl := rtl8720dn.New(uart)
|
||||
rtl.Debug(debug)
|
||||
|
||||
_, err := rtl.Rpc_tcpip_adapter_init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rtl, nil
|
||||
}
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
type UARTx struct {
|
||||
*machine.UART
|
||||
}
|
||||
|
||||
func (u UARTx) Read(p []byte) (n int, err error) {
|
||||
if u.Buffered() == 0 {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
return 0, nil
|
||||
}
|
||||
return u.UART.Read(p)
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/net"
|
||||
"tinygo.org/x/drivers/rtl8720dn"
|
||||
"tinygo.org/x/tinyfont/proggy"
|
||||
"tinygo.org/x/tinyterm"
|
||||
)
|
||||
|
||||
// You can override the setting with the init() in another source code.
|
||||
// func init() {
|
||||
// ssid = "your-ssid"
|
||||
// password = "your-password"
|
||||
// debug = true
|
||||
// server = "tinygo.org"
|
||||
// }
|
||||
|
||||
var (
|
||||
ssid string
|
||||
password string
|
||||
server string = "tinygo.org"
|
||||
debug = false
|
||||
)
|
||||
|
||||
var (
|
||||
terminal = tinyterm.NewTerminal(display)
|
||||
|
||||
black = color.RGBA{0, 0, 0, 255}
|
||||
white = color.RGBA{255, 255, 255, 255}
|
||||
red = color.RGBA{255, 0, 0, 255}
|
||||
blue = color.RGBA{0, 0, 255, 255}
|
||||
green = color.RGBA{0, 255, 0, 255}
|
||||
|
||||
font = &proggy.TinySZ8pt7b
|
||||
)
|
||||
|
||||
var buf [0x400]byte
|
||||
|
||||
var lastRequestTime time.Time
|
||||
var conn net.Conn
|
||||
var adaptor *rtl8720dn.RTL8720DN
|
||||
|
||||
func main() {
|
||||
display.FillScreen(black)
|
||||
backlight.High()
|
||||
|
||||
terminal.Configure(&tinyterm.Config{
|
||||
Font: font,
|
||||
FontHeight: 10,
|
||||
FontOffset: 6,
|
||||
})
|
||||
|
||||
err := run()
|
||||
for err != nil {
|
||||
fmt.Fprintf(terminal, "error: %s\r\n", err.Error())
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
fmt.Fprintf(terminal, "setupRTL8720DN()\r\n")
|
||||
rtl, err := setupRTL8720DN()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
net.UseDriver(rtl)
|
||||
|
||||
fmt.Fprintf(terminal, "ConnectToAP()\r\n")
|
||||
err = rtl.ConnectToAP(ssid, password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(terminal, "connected\r\n\r\n")
|
||||
|
||||
ip, subnet, gateway, err := rtl.GetIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(terminal, "IP Address : %s\r\n", ip)
|
||||
fmt.Fprintf(terminal, "Mask : %s\r\n", subnet)
|
||||
fmt.Fprintf(terminal, "Gateway : %s\r\n", gateway)
|
||||
|
||||
cnt := 0
|
||||
for {
|
||||
readConnection()
|
||||
if time.Now().Sub(lastRequestTime).Milliseconds() >= 10000 {
|
||||
makeHTTPRequest()
|
||||
cnt++
|
||||
fmt.Fprintf(terminal, "-------- %d --------\r\n", cnt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readConnection() {
|
||||
if conn != nil {
|
||||
for n, err := conn.Read(buf[:]); n > 0; n, err = conn.Read(buf[:]) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(terminal, "Read error: "+err.Error()+"\r\n")
|
||||
} else {
|
||||
fmt.Fprintf(terminal, string(buf[0:n]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
fmt.Fprintf(terminal, "Connected!\r\n")
|
||||
|
||||
fmt.Fprintf(terminal, "Sending HTTP request...")
|
||||
fmt.Fprintln(conn, "GET / HTTP/1.1")
|
||||
fmt.Fprintln(conn, "Host:", server)
|
||||
fmt.Fprintln(conn, "User-Agent: TinyGo")
|
||||
fmt.Fprintln(conn, "Connection: close")
|
||||
fmt.Fprintln(conn)
|
||||
fmt.Fprintf(terminal, "Sent!\r\n\r\n")
|
||||
|
||||
lastRequestTime = time.Now()
|
||||
}
|
||||
|
||||
func message(msg string) {
|
||||
fmt.Fprintf(terminal, "%s\r\n", msg)
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// +build wioterminal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"device/sam"
|
||||
"machine"
|
||||
"runtime/interrupt"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/ili9341"
|
||||
"tinygo.org/x/drivers/rtl8720dn"
|
||||
)
|
||||
|
||||
var (
|
||||
uart UARTx
|
||||
)
|
||||
|
||||
var (
|
||||
display = ili9341.NewSPI(
|
||||
machine.SPI3,
|
||||
machine.LCD_DC,
|
||||
machine.LCD_SS_PIN,
|
||||
machine.LCD_RESET,
|
||||
)
|
||||
|
||||
backlight = machine.LCD_BACKLIGHT
|
||||
)
|
||||
|
||||
func init() {
|
||||
machine.SPI3.Configure(machine.SPIConfig{
|
||||
SCK: machine.LCD_SCK_PIN,
|
||||
SDO: machine.LCD_SDO_PIN,
|
||||
SDI: machine.LCD_SDI_PIN,
|
||||
Frequency: 40000000,
|
||||
})
|
||||
display.Configure(ili9341.Config{})
|
||||
|
||||
backlight.Configure(machine.PinConfig{machine.PinOutput})
|
||||
}
|
||||
|
||||
func handleInterrupt(interrupt.Interrupt) {
|
||||
// should reset IRQ
|
||||
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
|
||||
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
|
||||
}
|
||||
|
||||
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
|
||||
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
machine.RTL8720D_CHIP_PU.Low()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
machine.RTL8720D_CHIP_PU.High()
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
if debug {
|
||||
waitSerial()
|
||||
}
|
||||
|
||||
uart = UARTx{
|
||||
UART: &machine.UART{
|
||||
Buffer: machine.NewRingBuffer(),
|
||||
Bus: sam.SERCOM0_USART_INT,
|
||||
SERCOM: 0,
|
||||
},
|
||||
}
|
||||
|
||||
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
|
||||
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
|
||||
|
||||
rtl := rtl8720dn.New(uart)
|
||||
rtl.Debug(debug)
|
||||
|
||||
_, err := rtl.Rpc_tcpip_adapter_init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rtl, nil
|
||||
}
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
type UARTx struct {
|
||||
*machine.UART
|
||||
}
|
||||
|
||||
func (u UARTx) Read(p []byte) (n int, err error) {
|
||||
if u.Buffered() == 0 {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
return 0, nil
|
||||
}
|
||||
return u.UART.Read(p)
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/net"
|
||||
"tinygo.org/x/drivers/rtl8720dn"
|
||||
)
|
||||
|
||||
// You can override the setting with the init() in another source code.
|
||||
// func init() {
|
||||
// ssid = "your-ssid"
|
||||
// password = "your-password"
|
||||
// debug = true
|
||||
// server = "tinygo.org"
|
||||
// }
|
||||
|
||||
var (
|
||||
ssid string
|
||||
password string
|
||||
server string = "tinygo.org"
|
||||
debug = false
|
||||
)
|
||||
|
||||
var buf [0x400]byte
|
||||
|
||||
var lastRequestTime time.Time
|
||||
var conn net.Conn
|
||||
var adaptor *rtl8720dn.RTL8720DN
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
for err != nil {
|
||||
fmt.Printf("error: %s\r\n", err.Error())
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
rtl, err := setupRTL8720DN()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
net.UseDriver(rtl)
|
||||
|
||||
err = rtl.ConnectToAP(ssid, password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ip, subnet, gateway, err := rtl.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)
|
||||
|
||||
cnt := 0
|
||||
for {
|
||||
readConnection()
|
||||
if time.Now().Sub(lastRequestTime).Milliseconds() >= 10000 {
|
||||
makeHTTPRequest()
|
||||
cnt++
|
||||
fmt.Printf("-------- %d --------\r\n", cnt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readConnection() {
|
||||
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]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
fmt.Fprintln(conn, "Connection: close")
|
||||
fmt.Fprintln(conn)
|
||||
println("Sent!\r\n\r")
|
||||
|
||||
lastRequestTime = time.Now()
|
||||
}
|
||||
|
||||
func message(msg string) {
|
||||
println(msg, "\r")
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// +build wioterminal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"device/sam"
|
||||
"machine"
|
||||
"runtime/interrupt"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/rtl8720dn"
|
||||
)
|
||||
|
||||
var (
|
||||
uart UARTx
|
||||
)
|
||||
|
||||
func handleInterrupt(interrupt.Interrupt) {
|
||||
// should reset IRQ
|
||||
uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
|
||||
uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
|
||||
}
|
||||
|
||||
func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
|
||||
machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
machine.RTL8720D_CHIP_PU.Low()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
machine.RTL8720D_CHIP_PU.High()
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
waitSerial()
|
||||
|
||||
uart = UARTx{
|
||||
UART: &machine.UART{
|
||||
Buffer: machine.NewRingBuffer(),
|
||||
Bus: sam.SERCOM0_USART_INT,
|
||||
SERCOM: 0,
|
||||
},
|
||||
}
|
||||
|
||||
uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
|
||||
uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
|
||||
|
||||
rtl := rtl8720dn.New(uart)
|
||||
rtl.Debug(debug)
|
||||
|
||||
_, err := rtl.Rpc_tcpip_adapter_init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rtl, nil
|
||||
}
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
type UARTx struct {
|
||||
*machine.UART
|
||||
}
|
||||
|
||||
func (u UARTx) Read(p []byte) (n int, err error) {
|
||||
if u.Buffered() == 0 {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
return 0, nil
|
||||
}
|
||||
return u.UART.Read(p)
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"machine"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/sdcard"
|
||||
)
|
||||
|
||||
const consoleBufLen = 64
|
||||
const storageBufLen = 1024
|
||||
|
||||
var (
|
||||
debug = false
|
||||
|
||||
input [consoleBufLen]byte
|
||||
store [storageBufLen]byte
|
||||
|
||||
console = machine.Serial
|
||||
|
||||
dev *sdcard.Device
|
||||
|
||||
commands map[string]cmdfunc = map[string]cmdfunc{
|
||||
"": cmdfunc(noop),
|
||||
"help": cmdfunc(help),
|
||||
"dbg": cmdfunc(dbg),
|
||||
"erase": cmdfunc(erase),
|
||||
"lsblk": cmdfunc(lsblk),
|
||||
"write": cmdfunc(write),
|
||||
"xxd": cmdfunc(xxd),
|
||||
}
|
||||
|
||||
his history
|
||||
)
|
||||
|
||||
type history struct {
|
||||
buf [32]string
|
||||
wp int
|
||||
idx int
|
||||
}
|
||||
|
||||
func (h *history) Add(cmd string) {
|
||||
if len(cmd) == 0 {
|
||||
h.idx = h.wp
|
||||
return
|
||||
}
|
||||
|
||||
if h.wp == len(h.buf)-1 {
|
||||
for i := 1; i < len(h.buf); i++ {
|
||||
h.buf[i-1] = h.buf[i]
|
||||
}
|
||||
h.wp--
|
||||
}
|
||||
|
||||
h.buf[h.wp] = cmd
|
||||
h.wp++
|
||||
h.idx = h.wp
|
||||
}
|
||||
|
||||
func (h *history) PeekPrev() string {
|
||||
if h.idx > 0 {
|
||||
h.idx--
|
||||
}
|
||||
return h.buf[h.idx]
|
||||
}
|
||||
|
||||
func (h *history) PeekNext() string {
|
||||
if h.idx < h.wp {
|
||||
h.idx++
|
||||
}
|
||||
return h.buf[h.idx]
|
||||
}
|
||||
|
||||
type cmdfunc func(argv []string)
|
||||
|
||||
const (
|
||||
StateInput = iota
|
||||
StateEscape
|
||||
StateEscBrc
|
||||
StateCSI
|
||||
)
|
||||
|
||||
func RunFor(device *sdcard.Device) {
|
||||
|
||||
dev = device
|
||||
|
||||
prompt()
|
||||
|
||||
var state = StateInput
|
||||
|
||||
for i := 0; ; {
|
||||
if console.Buffered() > 0 {
|
||||
data, _ := console.ReadByte()
|
||||
if debug {
|
||||
fmt.Printf("\rdata: %x, his.idx: %d\r\n\r", data, his.idx)
|
||||
prompt()
|
||||
console.Write(input[:i])
|
||||
}
|
||||
switch state {
|
||||
case StateInput:
|
||||
switch data {
|
||||
case 0x8:
|
||||
fallthrough
|
||||
case 0x7f: // this is probably wrong... works on my machine tho :)
|
||||
// backspace
|
||||
if i > 0 {
|
||||
i -= 1
|
||||
console.Write([]byte{0x8, 0x20, 0x8})
|
||||
}
|
||||
case 13:
|
||||
// return key
|
||||
console.Write([]byte("\r\n"))
|
||||
runCommand(string(input[:i]))
|
||||
his.Add(string(input[:i]))
|
||||
prompt()
|
||||
|
||||
i = 0
|
||||
continue
|
||||
case 27:
|
||||
// escape
|
||||
state = StateEscape
|
||||
default:
|
||||
// anything else, just echo the character if it is printable
|
||||
if strconv.IsPrint(rune(data)) {
|
||||
if i < (consoleBufLen - 1) {
|
||||
console.WriteByte(data)
|
||||
input[i] = data
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
case StateEscape:
|
||||
switch data {
|
||||
case 0x5b:
|
||||
state = StateEscBrc
|
||||
default:
|
||||
state = StateInput
|
||||
}
|
||||
case StateEscBrc:
|
||||
switch data {
|
||||
case 0x41:
|
||||
// up
|
||||
println()
|
||||
prompt()
|
||||
cmd := his.PeekPrev()
|
||||
i = len(cmd)
|
||||
copy(input[:i], []byte(cmd))
|
||||
console.Write(input[:i])
|
||||
state = StateInput
|
||||
case 0x42:
|
||||
//down
|
||||
println()
|
||||
prompt()
|
||||
cmd := his.PeekNext()
|
||||
i = len(cmd)
|
||||
copy(input[:i], []byte(cmd))
|
||||
console.Write(input[:i])
|
||||
state = StateInput
|
||||
default:
|
||||
// TODO: handle escape sequences
|
||||
state = StateInput
|
||||
}
|
||||
default:
|
||||
// TODO: handle escape sequences
|
||||
state = StateInput
|
||||
}
|
||||
} else {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runCommand(line string) {
|
||||
argv := strings.SplitN(strings.TrimSpace(line), " ", -1)
|
||||
cmd := argv[0]
|
||||
|
||||
cmdfn, ok := commands[cmd]
|
||||
if !ok {
|
||||
println("unknown command: " + line)
|
||||
return
|
||||
}
|
||||
cmdfn(argv)
|
||||
}
|
||||
|
||||
func noop(argv []string) {}
|
||||
|
||||
func help(argv []string) {
|
||||
fmt.Printf("help\r\n")
|
||||
fmt.Printf("dbg\r\n")
|
||||
fmt.Printf("erase\r\n")
|
||||
fmt.Printf("lsblk\r\n")
|
||||
fmt.Printf("write <hex offset> <bytes>\r\n")
|
||||
fmt.Printf("xxd <start address> <length>\r\n")
|
||||
}
|
||||
|
||||
func dbg(argv []string) {
|
||||
if debug {
|
||||
debug = false
|
||||
println("Console debbuging off")
|
||||
} else {
|
||||
debug = true
|
||||
println("Console debbuging on")
|
||||
}
|
||||
}
|
||||
|
||||
func lsblk(argv []string) {
|
||||
csd := dev.CSD
|
||||
sectors, err := csd.Sectors()
|
||||
if err != nil {
|
||||
fmt.Printf("%s\r\n", err.Error())
|
||||
return
|
||||
}
|
||||
cid := dev.CID
|
||||
|
||||
fmt.Printf(
|
||||
"\r\n-------------------------------------\r\n"+
|
||||
" Device Information: \r\n"+
|
||||
"-------------------------------------\r\n"+
|
||||
" JEDEC ID: %v\r\n"+
|
||||
" Serial: %v\r\n"+
|
||||
" Status 1: %02x\r\n"+
|
||||
" Status 2: %02x\r\n"+
|
||||
" \r\n"+
|
||||
" Max clock speed (MHz): %d\r\n"+
|
||||
" Has Sector Protection: %t\r\n"+
|
||||
" Supports Fast Reads: %t\r\n"+
|
||||
" Supports QSPI Reads: %t\r\n"+
|
||||
" Supports QSPI Write: %t\r\n"+
|
||||
" Write Status Split: %t\r\n"+
|
||||
" Single Status Byte: %t\r\n"+
|
||||
"-Sectors: %d\r\n"+
|
||||
"-Bytes (Sectors * 512) %d\r\n"+
|
||||
"-ManufacturerID %02X\r\n"+
|
||||
"-OEMApplicationID %04X\r\n"+
|
||||
"-ProductName %s\r\n"+
|
||||
"-ProductVersion %s\r\n"+
|
||||
"-ProductSerialNumber %08X\r\n"+
|
||||
"-ManufacturingYear %02X\r\n"+
|
||||
"-ManufacturingMonth %02X\r\n"+
|
||||
"-Always1 %d\r\n"+
|
||||
"-CRC %02X\r\n"+
|
||||
"-------------------------------------\r\n\r\n",
|
||||
"attrs.JedecID", // attrs.JedecID,
|
||||
cid.ProductSerialNumber, // serialNumber1,
|
||||
0, // status1,
|
||||
0, // status2,
|
||||
csd.TRAN_SPEED, // attrs.MaxClockSpeedMHz,
|
||||
false, // attrs.HasSectorProtection,
|
||||
false, // attrs.SupportsFastRead,
|
||||
false, // attrs.SupportsQSPI,
|
||||
false, // attrs.SupportsQSPIWrites,
|
||||
false, // attrs.WriteStatusSplit,
|
||||
false, // attrs.SingleStatusByte,
|
||||
sectors,
|
||||
csd.Size(),
|
||||
cid.ManufacturerID,
|
||||
cid.OEMApplicationID,
|
||||
cid.ProductName,
|
||||
cid.ProductVersion,
|
||||
cid.ProductSerialNumber,
|
||||
cid.ManufacturingYear,
|
||||
cid.ManufacturingMonth,
|
||||
cid.Always1,
|
||||
cid.CRC,
|
||||
)
|
||||
}
|
||||
|
||||
func erase(argv []string) {
|
||||
fmt.Printf("erase - not impl\r\n")
|
||||
}
|
||||
|
||||
var writeBuf [256]byte
|
||||
|
||||
func write(argv []string) {
|
||||
if len(argv) < 3 {
|
||||
println("usage: write <hex offset> <bytes>")
|
||||
return
|
||||
}
|
||||
var err error
|
||||
var addr uint64 = 0x0
|
||||
if addr, err = strconv.ParseUint(argv[1], 16, 32); err != nil {
|
||||
println("Invalid address: " + err.Error() + "\r\n")
|
||||
return
|
||||
}
|
||||
buf := writeBuf[:0]
|
||||
for i := 0; i < len(argv[2]); i += 2 {
|
||||
var b uint64
|
||||
if b, err = strconv.ParseUint(argv[2][i:i+2], 16, 8); err != nil {
|
||||
println("Invalid bytes: " + err.Error() + "\r\n")
|
||||
return
|
||||
}
|
||||
buf = append(buf, byte(b))
|
||||
}
|
||||
|
||||
if _, err = dev.WriteAt(buf, int64(addr)); err != nil {
|
||||
println("Write error: " + err.Error() + "\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
func xxd(argv []string) {
|
||||
var err error
|
||||
var addr uint64 = 0x0
|
||||
var size int = 64
|
||||
switch len(argv) {
|
||||
case 3:
|
||||
if size, err = strconv.Atoi(argv[2]); err != nil {
|
||||
println("Invalid size argument: " + err.Error() + "\r\n")
|
||||
return
|
||||
}
|
||||
if size > storageBufLen || size < 1 {
|
||||
fmt.Printf("Size of hexdump must be greater than 0 and less than %d\r\n", storageBufLen)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 2:
|
||||
if addr, err = strconv.ParseUint(argv[1], 16, 32); err != nil {
|
||||
println("Invalid address: " + err.Error() + "\r\n")
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 1:
|
||||
// no args supplied, so nothing to do here, just use the defaults
|
||||
default:
|
||||
println("usage: xxd <hex address, ex: 0xA0> <size of hexdump in bytes>\r\n")
|
||||
return
|
||||
}
|
||||
buf := store[0:size]
|
||||
_, err = dev.ReadAt(buf, int64(addr))
|
||||
if err != nil {
|
||||
fmt.Printf("xxd err : %s\r\n", err.Error())
|
||||
}
|
||||
xxdfprint(os.Stdout, uint32(addr), buf)
|
||||
}
|
||||
|
||||
func xxdfprint(w io.Writer, offset uint32, b []byte) {
|
||||
var l int
|
||||
var buf16 = make([]byte, 16)
|
||||
for i, c := 0, len(b); i < c; i += 16 {
|
||||
l = i + 16
|
||||
if l >= c {
|
||||
l = c
|
||||
}
|
||||
fmt.Fprintf(w, "%08x: % x ", offset+uint32(i), b[i:l])
|
||||
for j, n := 0, l-i; j < 16; j++ {
|
||||
if j >= n || !strconv.IsPrint(rune(b[i+j])) || b[i+j] >= 0x80 {
|
||||
buf16[j] = '.'
|
||||
} else {
|
||||
buf16[j] = b[i+j]
|
||||
}
|
||||
}
|
||||
console.Write(buf16)
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
func prompt() {
|
||||
print("==> ")
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build feather_m4 feather_m4_can feather_nrf52840
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D10
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build grandcentral-m4
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI1
|
||||
sckPin = machine.SDCARD_SCK_PIN
|
||||
sdoPin = machine.SDCARD_SDO_PIN
|
||||
sdiPin = machine.SDCARD_SDI_PIN
|
||||
csPin = machine.SDCARD_CS_PIN
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build atsamd21,!p1am_100
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D2
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/sdcard"
|
||||
)
|
||||
|
||||
var (
|
||||
spi machine.SPI
|
||||
sckPin machine.Pin
|
||||
sdoPin machine.Pin
|
||||
sdiPin machine.Pin
|
||||
csPin machine.Pin
|
||||
ledPin machine.Pin
|
||||
)
|
||||
|
||||
func main() {
|
||||
waitSerial()
|
||||
fmt.Printf("sdcard console\r\n")
|
||||
|
||||
led := ledPin
|
||||
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
sd := sdcard.New(spi, sckPin, sdoPin, sdiPin, csPin)
|
||||
err := sd.Configure()
|
||||
if err != nil {
|
||||
fmt.Printf("%s\r\n", err.Error())
|
||||
for {
|
||||
time.Sleep(time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
go RunFor(&sd)
|
||||
|
||||
for {
|
||||
led.High()
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
led.Low()
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build p1am_100
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SDCARD_SPI
|
||||
sckPin = machine.SDCARD_SCK_PIN
|
||||
sdoPin = machine.SDCARD_SDO_PIN
|
||||
sdiPin = machine.SDCARD_SDI_PIN
|
||||
csPin = machine.SDCARD_SS_PIN
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build pygamer
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D4
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build pyportal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D32 // SD_CS
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build wioterminal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI2
|
||||
sckPin = machine.SCK2
|
||||
sdoPin = machine.SDO2
|
||||
sdiPin = machine.SDI2
|
||||
csPin = machine.SS2
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,542 @@
|
||||
// +build tinygo
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"machine"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/tinyfs"
|
||||
)
|
||||
|
||||
const consoleBufLen = 64
|
||||
|
||||
const startBlock = 0
|
||||
const blockCount = 0
|
||||
|
||||
var (
|
||||
debug = false
|
||||
|
||||
input [consoleBufLen]byte
|
||||
|
||||
console = machine.Serial
|
||||
readyLED = machine.LED
|
||||
|
||||
flashdev tinyfs.BlockDevice
|
||||
fs tinyfs.Filesystem
|
||||
|
||||
currdir = "/"
|
||||
|
||||
commands = map[string]cmdfunc{
|
||||
"": noop,
|
||||
"dbg": dbg,
|
||||
"help": help,
|
||||
"lsblk": lsblk,
|
||||
"mount": mount,
|
||||
"umount": umount,
|
||||
"format": format,
|
||||
"xxd": xxd,
|
||||
"ls": ls,
|
||||
"samples": samples,
|
||||
"mkdir": mkdir,
|
||||
"cat": cat,
|
||||
"create": create,
|
||||
"write": write,
|
||||
"rm": rm,
|
||||
}
|
||||
)
|
||||
|
||||
type cmdfunc func(argv []string)
|
||||
|
||||
const (
|
||||
StateInput = iota
|
||||
StateEscape
|
||||
StateEscBrc
|
||||
StateCSI
|
||||
)
|
||||
|
||||
func RunFor(dev tinyfs.BlockDevice, filesys tinyfs.Filesystem) {
|
||||
flashdev = dev
|
||||
fs = filesys
|
||||
|
||||
readyLED.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
readyLED.High()
|
||||
|
||||
readyLED.Low()
|
||||
println("SPI Configured. Reading flash info")
|
||||
|
||||
/*
|
||||
lfsConfig := flashlfs.NewConfig()
|
||||
if blockCount == 0 {
|
||||
lfsConfig.BlockCount = (flashdev.Attrs().TotalSize / lfsConfig.BlockSize) - startBlock
|
||||
} else {
|
||||
lfsConfig.BlockCount = blockCount
|
||||
}
|
||||
println("Start block:", startBlock)
|
||||
println("Block count:", lfsConfig.BlockCount)
|
||||
|
||||
blockdev = flashlfs.NewBlockDevice(flashdev, startBlock, lfsConfig.BlockSize)
|
||||
*/
|
||||
|
||||
prompt()
|
||||
|
||||
var state = StateInput
|
||||
|
||||
for i := 0; ; {
|
||||
if console.Buffered() > 0 {
|
||||
data, _ := console.ReadByte()
|
||||
if debug {
|
||||
fmt.Printf("\rdata: %x\r\n\r", data)
|
||||
prompt()
|
||||
console.Write(input[:i])
|
||||
}
|
||||
switch state {
|
||||
case StateInput:
|
||||
switch data {
|
||||
case 0x8:
|
||||
fallthrough
|
||||
case 0x7f: // this is probably wrong... works on my machine tho :)
|
||||
// backspace
|
||||
if i > 0 {
|
||||
i -= 1
|
||||
console.Write([]byte{0x8, 0x20, 0x8})
|
||||
}
|
||||
case 13:
|
||||
// return key
|
||||
if console.Buffered() > 0 {
|
||||
data, _ := console.ReadByte()
|
||||
if data != 10 {
|
||||
println("\r\nunexpected: \r", int(data))
|
||||
}
|
||||
}
|
||||
console.Write([]byte("\r\n"))
|
||||
runCommand(string(input[:i]))
|
||||
prompt()
|
||||
|
||||
i = 0
|
||||
continue
|
||||
case 27:
|
||||
// escape
|
||||
state = StateEscape
|
||||
default:
|
||||
// anything else, just echo the character if it is printable
|
||||
if strconv.IsPrint(rune(data)) {
|
||||
if i < (consoleBufLen - 1) {
|
||||
console.WriteByte(data)
|
||||
input[i] = data
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
case StateEscape:
|
||||
switch data {
|
||||
case 0x5b:
|
||||
state = StateEscBrc
|
||||
default:
|
||||
state = StateInput
|
||||
}
|
||||
default:
|
||||
// TODO: handle escape sequences
|
||||
state = StateInput
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runCommand(line string) {
|
||||
argv := strings.SplitN(strings.TrimSpace(line), " ", -1)
|
||||
cmd := argv[0]
|
||||
cmdfn, ok := commands[cmd]
|
||||
if !ok {
|
||||
println("unknown command: " + line)
|
||||
return
|
||||
}
|
||||
cmdfn(argv)
|
||||
}
|
||||
|
||||
func noop(argv []string) {}
|
||||
|
||||
func help(argv []string) {
|
||||
fmt.Printf("help\r\n")
|
||||
fmt.Printf(" show help\r\n")
|
||||
fmt.Printf("dbg\r\n")
|
||||
fmt.Printf(" toggle debug mode\r\n")
|
||||
fmt.Printf("xxd <hex address, ex: 0xA0> <size of hexdump in bytes>\r\n")
|
||||
fmt.Printf(" hexdump the specified address\r\n")
|
||||
fmt.Printf("ls <target file>\r\n")
|
||||
fmt.Printf(" list information\r\n")
|
||||
fmt.Printf("samples\r\n")
|
||||
fmt.Printf(" write some files in the root directory\r\n")
|
||||
fmt.Printf("mkdir <target dir>\r\n")
|
||||
fmt.Printf(" create directory\r\n")
|
||||
fmt.Printf("cat <target file>\r\n")
|
||||
fmt.Printf(" print the contents of file\r\n")
|
||||
fmt.Printf("create <target file>\r\n")
|
||||
fmt.Printf(" create file\r\n")
|
||||
fmt.Printf("write <target file>\r\n")
|
||||
fmt.Printf(" write to file (press CTRL-D to exit)\r\n")
|
||||
fmt.Printf("rm\r\n")
|
||||
}
|
||||
|
||||
func dbg(argv []string) {
|
||||
if debug {
|
||||
debug = false
|
||||
println("Console debugging off")
|
||||
} else {
|
||||
debug = true
|
||||
println("Console debugging on")
|
||||
}
|
||||
}
|
||||
|
||||
func lsblk(argv []string) {
|
||||
fmt.Printf("lsblk : not implement\r\n")
|
||||
}
|
||||
|
||||
func mount(argv []string) {
|
||||
if err := fs.Mount(); err != nil {
|
||||
println("Could not mount LittleFS filesystem: " + err.Error() + "\r\n")
|
||||
} else {
|
||||
println("Successfully mounted LittleFS filesystem.\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
func format(argv []string) {
|
||||
if err := fs.Format(); err != nil {
|
||||
println("Could not format LittleFS filesystem: " + err.Error() + "\r\n")
|
||||
} else {
|
||||
println("Successfully formatted LittleFS filesystem.\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
func umount(argv []string) {
|
||||
if err := fs.Unmount(); err != nil {
|
||||
println("Could not unmount LittleFS filesystem: " + err.Error() + "\r\n")
|
||||
} else {
|
||||
println("Successfully unmounted LittleFS filesystem.\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
var err error
|
||||
if fatfs == nil {
|
||||
fatfs, err = fat.New(fatdisk)
|
||||
if err != nil {
|
||||
fatfs = nil
|
||||
println("could not load FAT filesystem: " + err.Error() + "\r\n")
|
||||
}
|
||||
fmt.Printf("loaded fs\r\n")
|
||||
}
|
||||
if rootdir == nil {
|
||||
rootdir, err = fatfs.RootDir()
|
||||
if err != nil {
|
||||
rootdir = nil
|
||||
println("could not load rootdir: " + err.Error() + "\r\n")
|
||||
}
|
||||
fmt.Printf("loaded rootdir\r\n")
|
||||
}
|
||||
if currdir == nil {
|
||||
currdir = rootdir
|
||||
}
|
||||
*/
|
||||
|
||||
func ls(argv []string) {
|
||||
path := "/"
|
||||
if len(argv) > 1 {
|
||||
path = strings.TrimSpace(argv[1])
|
||||
}
|
||||
dir, err := fs.Open(path)
|
||||
if err != nil {
|
||||
fmt.Printf("Could not open directory %s: %v\r\n", path, err)
|
||||
return
|
||||
}
|
||||
defer dir.Close()
|
||||
infos, err := dir.Readdir(0)
|
||||
_ = infos
|
||||
if err != nil {
|
||||
fmt.Printf("Could not read directory %s: %v\r\n", path, err)
|
||||
return
|
||||
}
|
||||
for _, info := range infos {
|
||||
s := "-rwxrwxrwx"
|
||||
if info.IsDir() {
|
||||
s = "drwxrwxrwx"
|
||||
}
|
||||
fmt.Printf("%s %5d %s\r\n", s, info.Size(), info.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func mkdir(argv []string) {
|
||||
tgt := ""
|
||||
if len(argv) == 2 {
|
||||
tgt = strings.TrimSpace(argv[1])
|
||||
}
|
||||
if debug {
|
||||
println("Trying mkdir to " + tgt)
|
||||
}
|
||||
if tgt == "" {
|
||||
println("Usage: mkdir <target dir>")
|
||||
return
|
||||
}
|
||||
err := fs.Mkdir(tgt, 0777)
|
||||
if err != nil {
|
||||
println("Could not mkdir " + tgt + ": " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func rm(argv []string) {
|
||||
tgt := ""
|
||||
if len(argv) == 2 {
|
||||
tgt = strings.TrimSpace(argv[1])
|
||||
}
|
||||
if debug {
|
||||
println("Trying rm to " + tgt)
|
||||
}
|
||||
if tgt == "" {
|
||||
println("Usage: rm <target dir>")
|
||||
return
|
||||
}
|
||||
err := fs.Remove(tgt)
|
||||
if err != nil {
|
||||
println("Could not rm " + tgt + ": " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func samples(argv []string) {
|
||||
buf := make([]byte, 90)
|
||||
for i := 0; i < 5; i++ {
|
||||
name := fmt.Sprintf("file%d.txt", i)
|
||||
if bytes, err := createSampleFile(name, buf); err != nil {
|
||||
fmt.Printf("%s\r\n", err)
|
||||
return
|
||||
} else {
|
||||
fmt.Printf("wrote %d bytes to %s\r\n", bytes, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func create(argv []string) {
|
||||
tgt := ""
|
||||
if len(argv) == 2 {
|
||||
tgt = strings.TrimSpace(argv[1])
|
||||
}
|
||||
if debug {
|
||||
println("Trying create to " + tgt)
|
||||
}
|
||||
buf := make([]byte, 90)
|
||||
if bytes, err := createSampleFile(tgt, buf); err != nil {
|
||||
fmt.Printf("%s\r\n", err)
|
||||
return
|
||||
} else {
|
||||
fmt.Printf("wrote %d bytes to %s\r\n", bytes, tgt)
|
||||
}
|
||||
}
|
||||
|
||||
func write(argv []string) {
|
||||
tgt := ""
|
||||
if len(argv) == 2 {
|
||||
tgt = strings.TrimSpace(argv[1])
|
||||
}
|
||||
if debug {
|
||||
println("Trying receive to " + tgt)
|
||||
}
|
||||
buf := make([]byte, 1)
|
||||
f, err := fs.OpenFile(tgt, os.O_CREATE|os.O_WRONLY|os.O_TRUNC)
|
||||
if err != nil {
|
||||
fmt.Printf("error opening %s: %s\r\n", tgt, err.Error())
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
var n int
|
||||
for {
|
||||
if console.Buffered() > 0 {
|
||||
data, _ := console.ReadByte()
|
||||
switch data {
|
||||
case 0x04:
|
||||
fmt.Printf("wrote %d bytes to %s\r\n", n, tgt)
|
||||
return
|
||||
default:
|
||||
// anything else, just echo the character if it is printable
|
||||
if strconv.IsPrint(rune(data)) {
|
||||
console.WriteByte(data)
|
||||
}
|
||||
buf[0] = data
|
||||
if _, err := f.Write(buf); err != nil {
|
||||
fmt.Printf("\nerror writing: %s\r\n", err)
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createSampleFile(name string, buf []byte) (int, error) {
|
||||
for j := uint8(0); j < uint8(len(buf)); j++ {
|
||||
buf[j] = 0x20 + j
|
||||
}
|
||||
f, err := fs.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error opening %s: %s", name, err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
bytes, err := f.Write(buf)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error writing %s: %s", name, err.Error())
|
||||
}
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func cd(argv []string) {
|
||||
|
||||
if fatfs == nil || rootdir == nil {
|
||||
mnt(nil)
|
||||
}
|
||||
if len(argv) == 1 {
|
||||
currdir = rootdir
|
||||
return
|
||||
}
|
||||
tgt := ""
|
||||
if len(argv) == 2 {
|
||||
tgt = strings.TrimSpace(argv[1])
|
||||
}
|
||||
if debug {
|
||||
println("Trying to cd to " + tgt)
|
||||
}
|
||||
if tgt == "" {
|
||||
println("Usage: cd <target dir>")
|
||||
return
|
||||
}
|
||||
if debug {
|
||||
println("Getting entry")
|
||||
}
|
||||
entry := currdir.Entry(tgt)
|
||||
if entry == nil {
|
||||
println("File not found: " + tgt)
|
||||
return
|
||||
}
|
||||
if !entry.IsDir() {
|
||||
println("Not a directory: " + tgt)
|
||||
return
|
||||
}
|
||||
if debug {
|
||||
println("Getting dir")
|
||||
}
|
||||
cd, err := entry.Dir()
|
||||
if err != nil {
|
||||
println("Could not cd to " + tgt + ": " + err.Error())
|
||||
}
|
||||
currdir = cd
|
||||
}
|
||||
*/
|
||||
|
||||
func cat(argv []string) {
|
||||
tgt := ""
|
||||
if len(argv) == 2 {
|
||||
tgt = strings.TrimSpace(argv[1])
|
||||
}
|
||||
if debug {
|
||||
println("Trying to cat to " + tgt)
|
||||
}
|
||||
if tgt == "" {
|
||||
println("Usage: cat <target file>")
|
||||
return
|
||||
}
|
||||
if debug {
|
||||
println("Getting entry")
|
||||
}
|
||||
f, err := fs.Open(tgt)
|
||||
if err != nil {
|
||||
println("Could not open: " + err.Error())
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
if f.IsDir() {
|
||||
println("Not a file: " + tgt)
|
||||
return
|
||||
}
|
||||
off := 0x0
|
||||
buf := make([]byte, 64)
|
||||
for {
|
||||
n, err := f.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
println("Error reading " + tgt + ": " + err.Error())
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
xxdfprint(os.Stdout, uint32(off), buf[:n])
|
||||
off += n
|
||||
}
|
||||
}
|
||||
|
||||
func xxd(argv []string) {
|
||||
var err error
|
||||
var addr uint64 = 0x0
|
||||
var size int = 64
|
||||
switch len(argv) {
|
||||
case 3:
|
||||
if size, err = strconv.Atoi(argv[2]); err != nil {
|
||||
println("Invalid size argument: " + err.Error() + "\r\n")
|
||||
return
|
||||
}
|
||||
if size > 512 || size < 1 {
|
||||
fmt.Printf("Size of hexdump must be greater than 0 and less than %d\r\n", 512)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 2:
|
||||
/*
|
||||
if argv[1][:2] != "0x" {
|
||||
println("Invalid hex address (should start with 0x)")
|
||||
return
|
||||
}
|
||||
*/
|
||||
if addr, err = strconv.ParseUint(argv[1], 16, 32); err != nil {
|
||||
println("Invalid address: " + err.Error() + "\r\n")
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 1:
|
||||
// no args supplied, so nothing to do here, just use the defaults
|
||||
default:
|
||||
println("usage: xxd <hex address, ex: 0xA0> <size of hexdump in bytes>\r\n")
|
||||
return
|
||||
}
|
||||
buf := make([]byte, size)
|
||||
//bsz := uint64(flash.SectorSize)
|
||||
//blockdev.ReadBlock(uint32(addr/bsz), uint32(addr%bsz), buf)
|
||||
flashdev.ReadAt(buf, int64(addr))
|
||||
xxdfprint(os.Stdout, uint32(addr), buf)
|
||||
}
|
||||
|
||||
func xxdfprint(w io.Writer, offset uint32, b []byte) {
|
||||
var l int
|
||||
var buf16 = make([]byte, 16)
|
||||
for i, c := 0, len(b); i < c; i += 16 {
|
||||
l = i + 16
|
||||
if l >= c {
|
||||
l = c
|
||||
}
|
||||
fmt.Fprintf(w, "%08x: % x ", offset+uint32(i), b[i:l])
|
||||
for j, n := 0, l-i; j < 16; j++ {
|
||||
if j >= n || !strconv.IsPrint(rune(b[i+j])) || b[i+j] >= 0x80 {
|
||||
buf16[j] = '.'
|
||||
} else {
|
||||
buf16[j] = b[i+j]
|
||||
}
|
||||
}
|
||||
console.Write(buf16)
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
func prompt() {
|
||||
print("==> ")
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build feather_m4 feather_m4_can feather_nrf52840
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D10
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build grandcentral-m4
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI1
|
||||
sckPin = machine.SDCARD_SCK_PIN
|
||||
sdoPin = machine.SDCARD_SDO_PIN
|
||||
sdiPin = machine.SDCARD_SDI_PIN
|
||||
csPin = machine.SDCARD_CS_PIN
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build atsamd21,!p1am_100
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D2
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/examples/sdcard/tinyfs/console"
|
||||
"tinygo.org/x/drivers/sdcard"
|
||||
"tinygo.org/x/tinyfs/fatfs"
|
||||
)
|
||||
|
||||
var (
|
||||
spi machine.SPI
|
||||
sckPin machine.Pin
|
||||
sdoPin machine.Pin
|
||||
sdiPin machine.Pin
|
||||
csPin machine.Pin
|
||||
ledPin machine.Pin
|
||||
)
|
||||
|
||||
func main() {
|
||||
waitSerial()
|
||||
|
||||
sd := sdcard.New(spi, sckPin, sdoPin, sdiPin, csPin)
|
||||
err := sd.Configure()
|
||||
if err != nil {
|
||||
fmt.Printf("%s\r\n", err.Error())
|
||||
for {
|
||||
time.Sleep(time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
filesystem := fatfs.New(&sd)
|
||||
|
||||
// Configure FATFS with sector size (must match value in ff.h - use 512)
|
||||
filesystem.Configure(&fatfs.Config{
|
||||
SectorSize: 512,
|
||||
})
|
||||
|
||||
console.RunFor(&sd, filesystem)
|
||||
}
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build p1am_100
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SDCARD_SPI
|
||||
sckPin = machine.SDCARD_SCK_PIN
|
||||
sdoPin = machine.SDCARD_SDO_PIN
|
||||
sdiPin = machine.SDCARD_SDI_PIN
|
||||
csPin = machine.SDCARD_SS_PIN
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build pygamer
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D4
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build pyportal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI0
|
||||
sckPin = machine.SPI0_SCK_PIN
|
||||
sdoPin = machine.SPI0_SDO_PIN
|
||||
sdiPin = machine.SPI0_SDI_PIN
|
||||
csPin = machine.D32 // SD_CS
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// +build wioterminal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
spi = machine.SPI2
|
||||
sckPin = machine.SCK2
|
||||
sdoPin = machine.SDO2
|
||||
sdiPin = machine.SDI2
|
||||
csPin = machine.SS2
|
||||
|
||||
ledPin = machine.LED
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"machine"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/wifinina"
|
||||
@@ -52,15 +51,37 @@ func main() {
|
||||
connectToAP()
|
||||
|
||||
for {
|
||||
println("---------------------------------")
|
||||
println("----------------------------------------")
|
||||
printSSID()
|
||||
printRSSI()
|
||||
printMac()
|
||||
printIPs()
|
||||
printTime()
|
||||
printMacAddress()
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func printSSID() {
|
||||
print("SSID: ")
|
||||
ssid, err := adaptor.GetCurrentSSID()
|
||||
if err != nil {
|
||||
println("Unknown (error: ", err.Error(), ")")
|
||||
return
|
||||
}
|
||||
println(ssid)
|
||||
}
|
||||
|
||||
func printRSSI() {
|
||||
print("RSSI: ")
|
||||
rssi, err := adaptor.GetCurrentRSSI()
|
||||
if err != nil {
|
||||
println("Unknown (error: ", err.Error(), ")")
|
||||
return
|
||||
}
|
||||
println(strconv.Itoa(int(rssi)))
|
||||
}
|
||||
|
||||
func printIPs() {
|
||||
ip, subnet, gateway, err := adaptor.GetIP()
|
||||
if err != nil {
|
||||
@@ -69,39 +90,38 @@ func printIPs() {
|
||||
}
|
||||
println("IP: ", ip.String())
|
||||
println("Subnet: ", subnet.String())
|
||||
println("Gateway IP: ", gateway.String())
|
||||
println("Gateway: ", gateway.String())
|
||||
}
|
||||
|
||||
func printTime() {
|
||||
print("Time: ")
|
||||
t, err := adaptor.GetTime()
|
||||
if err != nil {
|
||||
println("Unknown (error: ", err.Error(), ")")
|
||||
for {
|
||||
if err != nil {
|
||||
println("Unknown (error: ", err.Error(), ")")
|
||||
return
|
||||
}
|
||||
if t != 0 {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
t, err = adaptor.GetTime()
|
||||
}
|
||||
println(time.Unix(int64(t), 0).String())
|
||||
}
|
||||
|
||||
func printMacAddress() {
|
||||
print("MAC Address: ")
|
||||
b := make([]byte, 8)
|
||||
func printMac() {
|
||||
print("MAC: ")
|
||||
mac, err := adaptor.GetMACAddress()
|
||||
if err != nil {
|
||||
println("Unknown (", err.Error(), ")")
|
||||
}
|
||||
binary.LittleEndian.PutUint64(b, uint64(mac))
|
||||
macAddress := ""
|
||||
for i := 5; i >= 0; i-- {
|
||||
macAddress += fmt.Sprintf("%0X", b[i])
|
||||
if i != 0 {
|
||||
macAddress += ":"
|
||||
}
|
||||
}
|
||||
println(macAddress)
|
||||
println(mac.String())
|
||||
}
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.UART0.DTR() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
@@ -115,16 +135,12 @@ func connectToAP() {
|
||||
}
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
message("Connecting to " + ssid)
|
||||
println("Connecting to " + ssid)
|
||||
adaptor.SetPassphrase(ssid, pass)
|
||||
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
|
||||
message("Connection status: " + st.String())
|
||||
println("Connection status: " + st.String())
|
||||
time.Sleep(1 * time.Second)
|
||||
st, _ = adaptor.GetConnectionStatus()
|
||||
}
|
||||
message("Connected.")
|
||||
}
|
||||
|
||||
func message(msg string) {
|
||||
println(msg, "\r")
|
||||
println("Connected.")
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func main() {
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.UART0.DTR() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func main() {
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.UART0.DTR() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func main() {
|
||||
|
||||
// Wait for user to open serial console
|
||||
func waitSerial() {
|
||||
for !machine.UART0.DTR() {
|
||||
for !machine.Serial.DTR() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package main
|
||||
|
||||
import "machine"
|
||||
|
||||
// Replace neo in the code below to match the pin
|
||||
// Replace neo and led in the code below to match the pin
|
||||
// that you are using if different.
|
||||
var neo = machine.D2
|
||||
var led = machine.LED
|
||||
|
||||
@@ -5,6 +5,7 @@ package main
|
||||
import "machine"
|
||||
|
||||
// This is the pin assignment for the Digispark only.
|
||||
// Replace neo in the code below to match the pin
|
||||
// Replace neo and led in the code below to match the pin
|
||||
// that you are using if different.
|
||||
var neo machine.Pin = 0
|
||||
var led = machine.LED
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
var leds [10]color.RGBA
|
||||
|
||||
func main() {
|
||||
led := machine.LED
|
||||
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
neo.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// +build !digispark,!arduino
|
||||
// +build !digispark,!arduino,!qtpy
|
||||
|
||||
package main
|
||||
|
||||
import "machine"
|
||||
|
||||
// Replace neo in the code below to match the pin
|
||||
// Replace neo and led in the code below to match the pin
|
||||
// that you are using if different.
|
||||
var neo machine.Pin = machine.NEOPIXELS
|
||||
var neo machine.Pin = machine.WS2812
|
||||
var led = machine.LED
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// +build qtpy
|
||||
|
||||
package main
|
||||
|
||||
import "machine"
|
||||
|
||||
// Replace neo and led in the code below to match the pin
|
||||
// that you are using if different.
|
||||
var neo machine.Pin = machine.NEOPIXELS
|
||||
var led = machine.NoPin
|
||||
|
||||
func init() {
|
||||
pwr := machine.NEOPIXELS_POWER
|
||||
pwr.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
pwr.High()
|
||||
}
|
||||
@@ -5,4 +5,7 @@ go 1.15
|
||||
require (
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0
|
||||
github.com/frankban/quicktest v1.10.2
|
||||
tinygo.org/x/tinyfont v0.2.1
|
||||
tinygo.org/x/tinyfs v0.1.0
|
||||
tinygo.org/x/tinyterm v0.1.0
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
github.com/bgould/http v0.0.0-20190627042742-d268792bdee7/go.mod h1:BTqvVegvwifopl4KTEDth6Zezs9eR+lCWhvGKvkxJHE=
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
|
||||
github.com/frankban/quicktest v1.10.2 h1:19ARM85nVi4xH7xPXuc5eM/udya5ieh7b/Sv+d844Tk=
|
||||
@@ -9,5 +10,15 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
tinygo.org/x/drivers v0.14.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
|
||||
tinygo.org/x/drivers v0.15.1/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
|
||||
tinygo.org/x/drivers v0.16.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
|
||||
tinygo.org/x/tinyfont v0.2.1 h1:FAaemBzw8wsfhAtG6fWW+QjyWw/K8YqEeiWo4N1pv4o=
|
||||
tinygo.org/x/tinyfont v0.2.1/go.mod h1:eLqnYSrFRjt5STxWaMeOWJTzrKhXqpWw7nU3bPfKOAM=
|
||||
tinygo.org/x/tinyfs v0.1.0 h1:yx1Tq9L60rpCm6HURo45x+Tnag+O9RGSbQfgeCb6XYU=
|
||||
tinygo.org/x/tinyfs v0.1.0/go.mod h1:ysc8Y92iHfhTXeyEM9+c7zviUQ4fN9UCFgSOFfMWv20=
|
||||
tinygo.org/x/tinyterm v0.1.0 h1:80i+j+KWoxCFa/Xfp6pWbh79x+8zUdMXC1vaKj2QhkY=
|
||||
tinygo.org/x/tinyterm v0.1.0/go.mod h1:/DDhNnGwNF2/tNgHywvyZuCGnbH3ov49Z/6e8LPLRR4=
|
||||
|
||||
+17
-1
@@ -160,6 +160,20 @@ func (d *Device) DrawRGBBitmap(x, y int16, data []uint16, w, h int16) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DrawRGBBitmap8 copies an RGB bitmap to the internal buffer at given coordinates
|
||||
func (d *Device) DrawRGBBitmap8(x, y int16, data []uint8, w, h int16) error {
|
||||
k, i := d.Size()
|
||||
if x < 0 || y < 0 || w <= 0 || h <= 0 ||
|
||||
x >= k || (x+w) > k || y >= i || (y+h) > i {
|
||||
return errors.New("rectangle coordinates outside display area")
|
||||
}
|
||||
d.setWindow(x, y, w, h)
|
||||
d.startWrite()
|
||||
d.driver.write8sl(data)
|
||||
d.endWrite()
|
||||
return nil
|
||||
}
|
||||
|
||||
// FillRectangle fills a rectangle at given coordinates with a color
|
||||
func (d *Device) FillRectangle(x, y, width, height int16, c color.RGBA) error {
|
||||
k, i := d.Size()
|
||||
@@ -300,7 +314,9 @@ func (d *Device) sendCommand(cmd byte, data []byte) {
|
||||
d.dc.Low()
|
||||
d.driver.write8(cmd)
|
||||
d.dc.High()
|
||||
d.driver.write8sl(data)
|
||||
if data != nil {
|
||||
d.driver.write8sl(data)
|
||||
}
|
||||
d.endWrite()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// +build !atsamd51,!atsamd21
|
||||
|
||||
package ili9341
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
var buf [64]byte
|
||||
|
||||
type spiDriver struct {
|
||||
bus machine.SPI
|
||||
}
|
||||
|
||||
func NewSPI(bus machine.SPI, dc, cs, rst machine.Pin) *Device {
|
||||
return &Device{
|
||||
dc: dc,
|
||||
cs: cs,
|
||||
rst: rst,
|
||||
rd: machine.NoPin,
|
||||
driver: &spiDriver{
|
||||
bus: bus,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *spiDriver) configure(config *Config) {
|
||||
}
|
||||
|
||||
func (pd *spiDriver) write8(b byte) {
|
||||
buf[0] = b
|
||||
pd.bus.Tx(buf[:1], nil)
|
||||
}
|
||||
|
||||
func (pd *spiDriver) write8n(b byte, n int) {
|
||||
buf[0] = b
|
||||
for i := 0; i < n; i++ {
|
||||
pd.bus.Tx(buf[:1], nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *spiDriver) write8sl(b []byte) {
|
||||
pd.bus.Tx(b, nil)
|
||||
}
|
||||
|
||||
func (pd *spiDriver) write16(data uint16) {
|
||||
buf[0] = uint8(data >> 8)
|
||||
buf[1] = uint8(data)
|
||||
pd.bus.Tx(buf[:2], nil)
|
||||
}
|
||||
|
||||
func (pd *spiDriver) write16n(data uint16, n int) {
|
||||
for i := 0; i < len(buf); i += 2 {
|
||||
buf[i] = uint8(data >> 8)
|
||||
buf[i+1] = uint8(data)
|
||||
}
|
||||
|
||||
for i := 0; i < (n >> 5); i++ {
|
||||
pd.bus.Tx(buf[:], nil)
|
||||
}
|
||||
|
||||
pd.bus.Tx(buf[:n%64], nil)
|
||||
}
|
||||
|
||||
func (pd *spiDriver) write16sl(data []uint16) {
|
||||
for i, c := 0, len(data); i < c; i++ {
|
||||
buf[0] = uint8(data[i] >> 8)
|
||||
buf[1] = uint8(data[i])
|
||||
pd.bus.Tx(buf[:2], nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# RTL8720DN Driver
|
||||
|
||||
This package provides a driver to use a separate connected WiFi processor `RTL8720DN` for TCP/UDP communication.
|
||||
At this time, only part of TCP is supported.
|
||||
|
||||
## Using th RTL8720DN Driver
|
||||
|
||||
For now, it is only available for the `RTL8720DN` on `Wio Terminal`.
|
||||
You can try the following command.
|
||||
|
||||
```
|
||||
$ tinygo flash --target wioterminal --size short ./examples/rtl8720dn/webclient/
|
||||
$ tinygo flash --target wioterminal --size short ./examples/rtl8720dn/tlsclient/
|
||||
```
|
||||
|
||||
## RTL8720DN Firmware
|
||||
|
||||
Follow the steps below to update.
|
||||
The firmware must be version 2.1.2 or later.
|
||||
|
||||
https://wiki.seeedstudio.com/Wio-Terminal-Network-Overview/
|
||||
@@ -0,0 +1,35 @@
|
||||
package rtl8720dn
|
||||
|
||||
// https://github.com/EmbeddedRPC/erpc/blob/develop/erpc_python/erpc/crc16.py
|
||||
|
||||
const (
|
||||
crcStart = 0xEF4A
|
||||
)
|
||||
|
||||
var table = [256]uint16{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
|
||||
}
|
||||
|
||||
func computeCRC16(data []byte) uint16 {
|
||||
crc := uint16(crcStart)
|
||||
|
||||
for _, d := range data {
|
||||
crc = ((crc << 8) ^ table[((crc>>8)^uint16(d))&0xFF]) & 0xFFFF
|
||||
}
|
||||
return crc
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
package rtl8720dn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Here is the implementation of tinygo-org/x/drivers/net.DeviceDriver.
|
||||
|
||||
func (r *RTL8720DN) GetDNS(domain string) (string, error) {
|
||||
if r.debug {
|
||||
fmt.Printf("GetDNS(%q)\r\n", domain)
|
||||
}
|
||||
|
||||
ipaddr := [4]byte{}
|
||||
_, err := r.Rpc_netconn_gethostbyname(domain, ipaddr[:])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ret, err := fmt.Sprintf("%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]), nil
|
||||
if r.debug {
|
||||
fmt.Printf("-> %s\r\n", ret)
|
||||
fmt.Printf("-> %02X.%02X.%02X.%02X\r\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3])
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) ConnectTCPSocket(addr, port string) error {
|
||||
if r.debug {
|
||||
fmt.Printf("ConnectTCPSocket(%q, %q)\r\n", addr, port)
|
||||
}
|
||||
|
||||
ipaddr := [4]byte{}
|
||||
_, err := r.Rpc_netconn_gethostbyname(addr, ipaddr[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portNum, err := strconv.ParseUint(port, 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
socket, err := r.Rpc_lwip_socket(0x02, 0x01, 0x00)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.socket = socket
|
||||
r.connectionType = ConnectionTypeTCP
|
||||
|
||||
_, err = r.Rpc_lwip_fcntl(socket, 0x00000003, 0x00000000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Rpc_lwip_fcntl(socket, 0x00000004, 0x00000001)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := []byte{0x00, 0x02, 0x00, 0x50, 0xC0, 0xA8, 0x01, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
name[2] = byte(portNum >> 8)
|
||||
name[3] = byte(portNum)
|
||||
name[4] = byte(ipaddr[0])
|
||||
name[5] = byte(ipaddr[1])
|
||||
name[6] = byte(ipaddr[2])
|
||||
name[7] = byte(ipaddr[3])
|
||||
|
||||
_, err = r.Rpc_lwip_connect(socket, name, uint32(len(name)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
readset := []byte{}
|
||||
writeset := []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
exceptset := []byte{}
|
||||
timeout := []byte{}
|
||||
_, err = r.Rpc_lwip_select(0x01, readset, writeset, exceptset, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
optlen := uint32(4)
|
||||
_, err = r.Rpc_lwip_getsockopt(socket, 0x00000FFF, 0x00001007, []byte{0xA5, 0xA5, 0xA5, 0xA5}, nil, optlen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Rpc_lwip_fcntl(socket, 0x00000003, 0x00000000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Rpc_lwip_fcntl(socket, 0x00000004, 0x00000000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
readset = []byte{}
|
||||
writeset = []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
exceptset = []byte{}
|
||||
timeout = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}
|
||||
_, err = r.Rpc_lwip_select(0x01, readset, writeset, exceptset, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) ConnectSSLSocket(addr, port string) error {
|
||||
if r.debug {
|
||||
fmt.Printf("ConnectSSLSocket(%q, %q)\r\n", addr, port)
|
||||
}
|
||||
|
||||
client, err := r.Rpc_wifi_ssl_client_create()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.client = client
|
||||
r.connectionType = ConnectionTypeTLS
|
||||
|
||||
err = r.Rpc_wifi_ssl_init(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.Rpc_wifi_ssl_set_timeout(client, 0x0001D4C0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Rpc_wifi_ssl_set_rootCA(client, *r.root_ca)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: use port
|
||||
_, err = r.Rpc_wifi_start_ssl_client(client, addr, 443, 0x0001D4C0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Rpc_wifi_ssl_get_socket(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) ConnectUDPSocket(addr, sendport, listenport string) error {
|
||||
if r.debug {
|
||||
fmt.Printf("ConnectUDPSocket(%q, %q, %q)\r\n", addr, sendport, listenport)
|
||||
}
|
||||
fmt.Printf("not implemented yet\r\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) DisconnectSocket() error {
|
||||
if r.debug {
|
||||
fmt.Printf("DisconnectSocket()\r\n")
|
||||
}
|
||||
switch r.connectionType {
|
||||
case ConnectionTypeTCP:
|
||||
_, err := r.Rpc_lwip_close(r.socket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case ConnectionTypeTLS:
|
||||
err := r.Rpc_wifi_stop_ssl_socket(r.client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.Rpc_wifi_ssl_client_destroy(r.client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
}
|
||||
r.connectionType = ConnectionTypeNone
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) StartSocketSend(size int) error {
|
||||
if r.debug {
|
||||
fmt.Printf("StartSocketSend(%d)\r\n", size)
|
||||
}
|
||||
// No implementation required
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) Write(b []byte) (n int, err error) {
|
||||
if r.debug {
|
||||
fmt.Printf("Write(%#v)\r\n", b)
|
||||
}
|
||||
|
||||
switch r.connectionType {
|
||||
case ConnectionTypeTCP:
|
||||
sn, err := r.Rpc_lwip_send(r.socket, b, 0x00000008)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n = int(sn)
|
||||
case ConnectionTypeTLS:
|
||||
sn, err := r.Rpc_wifi_send_ssl_data(r.client, b, uint16(len(b)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n = int(sn)
|
||||
default:
|
||||
return 0, nil
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) ReadSocket(b []byte) (n int, err error) {
|
||||
if r.debug {
|
||||
//fmt.Printf("ReadSocket(b)\r\n")
|
||||
}
|
||||
if r.connectionType == ConnectionTypeNone {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
switch r.connectionType {
|
||||
case ConnectionTypeTCP:
|
||||
nn, err := r.Rpc_lwip_recv(r.socket, b, uint32(len(b)), 0x00000008, 0x00002800)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if nn == -1 {
|
||||
return 0, nil
|
||||
} else if nn == 0 {
|
||||
return 0, r.DisconnectSocket()
|
||||
}
|
||||
if r.length == 0 {
|
||||
header := httpHeader(b[:nn])
|
||||
r.length = header.ContentLength()
|
||||
}
|
||||
r.length -= int(nn)
|
||||
if r.length == 0 {
|
||||
return int(nn), r.DisconnectSocket()
|
||||
}
|
||||
n = int(nn)
|
||||
case ConnectionTypeTLS:
|
||||
nn, err := r.Rpc_wifi_get_ssl_receive(r.client, b, int32(len(b)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if nn < 0 {
|
||||
return 0, fmt.Errorf("error %d", n)
|
||||
} else if nn == 0 || nn == -30848 {
|
||||
return 0, r.DisconnectSocket()
|
||||
}
|
||||
n = int(nn)
|
||||
default:
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) IsSocketDataAvailable() bool {
|
||||
if r.debug {
|
||||
fmt.Printf("IsSocketDataAvailable()\r\n")
|
||||
}
|
||||
fmt.Printf("not implemented yet\r\n")
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) Response(timeout int) ([]byte, error) {
|
||||
if r.debug {
|
||||
fmt.Printf("Response(%d))\r\n", timeout)
|
||||
}
|
||||
// No implementation required
|
||||
return nil, nil
|
||||
}
|
||||
+9422
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
||||
package rtl8720dn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
headerBuf [4]byte
|
||||
readBuf [4]byte
|
||||
startWriteMessageBuf [1024]byte
|
||||
payload [1024 + 256]byte
|
||||
)
|
||||
|
||||
const (
|
||||
xVersion = 1
|
||||
)
|
||||
|
||||
func startWriteMessage(msgType, service, requestNumber, sequence uint32) []byte {
|
||||
startWriteMessageBuf[0] = byte(msgType)
|
||||
startWriteMessageBuf[1] = byte(requestNumber)
|
||||
startWriteMessageBuf[2] = byte(service)
|
||||
startWriteMessageBuf[3] = byte(xVersion)
|
||||
|
||||
startWriteMessageBuf[4] = byte(sequence)
|
||||
startWriteMessageBuf[5] = byte(sequence >> 8)
|
||||
startWriteMessageBuf[6] = byte(sequence >> 16)
|
||||
startWriteMessageBuf[7] = byte(sequence >> 24)
|
||||
|
||||
return startWriteMessageBuf[:8]
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) performRequest(msg []byte) error {
|
||||
crc := computeCRC16(msg)
|
||||
headerBuf[0] = byte(len(msg))
|
||||
headerBuf[1] = byte(len(msg) >> 8)
|
||||
headerBuf[2] = byte(crc)
|
||||
headerBuf[3] = byte(crc >> 8)
|
||||
|
||||
if r.debug {
|
||||
fmt.Printf("tx : %2d : ", len(headerBuf))
|
||||
dumpHex(headerBuf[:])
|
||||
fmt.Printf("\r\n")
|
||||
}
|
||||
|
||||
r.port.Write(headerBuf[:])
|
||||
|
||||
if r.debug {
|
||||
fmt.Printf("tx : %2d : ", len(msg))
|
||||
dumpHex(msg)
|
||||
fmt.Printf("\r\n")
|
||||
}
|
||||
r.port.Write(msg)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dumpHex(b []byte) {
|
||||
for i := range b {
|
||||
if i == 0 {
|
||||
fmt.Printf("%02X", b[i])
|
||||
} else {
|
||||
fmt.Printf(" %02X", b[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) readThread() {
|
||||
for {
|
||||
n, _ := io.ReadFull(r.port, readBuf[:4])
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if r.debug {
|
||||
fmt.Printf("rx : %2d : ", n)
|
||||
dumpHex(readBuf[:n])
|
||||
fmt.Printf("\r\n")
|
||||
}
|
||||
|
||||
length := uint16(readBuf[0]) + uint16(readBuf[1])<<8
|
||||
crc := uint16(readBuf[2]) + uint16(readBuf[3])<<8
|
||||
|
||||
n, _ = io.ReadFull(r.port, payload[:length])
|
||||
if r.debug {
|
||||
fmt.Printf("rx : %2d : ", length)
|
||||
dumpHex(payload[0:n])
|
||||
fmt.Printf("\r\n")
|
||||
}
|
||||
|
||||
n = int(length)
|
||||
|
||||
crcNew := computeCRC16(payload[:n])
|
||||
if g, e := crcNew, crc; g != e {
|
||||
fmt.Printf("err CRC16: got %04X want %04X\n", g, e)
|
||||
}
|
||||
if payload[0] == 0x02 || payload[0] == 0x00 {
|
||||
r.received <- true
|
||||
|
||||
// switch goroutine
|
||||
time.Sleep(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package rtl8720dn
|
||||
|
||||
import "io"
|
||||
|
||||
type RTL8720DN struct {
|
||||
port io.ReadWriter
|
||||
seq uint64
|
||||
received chan bool
|
||||
debug bool
|
||||
|
||||
connectionType ConnectionType
|
||||
socket int32
|
||||
client uint32
|
||||
length int
|
||||
root_ca *string
|
||||
}
|
||||
|
||||
type ConnectionType int
|
||||
|
||||
const (
|
||||
ConnectionTypeNone ConnectionType = iota
|
||||
ConnectionTypeTCP
|
||||
ConnectionTypeUDP
|
||||
ConnectionTypeTLS
|
||||
)
|
||||
|
||||
func New(r io.ReadWriter) *RTL8720DN {
|
||||
ret := &RTL8720DN{
|
||||
port: r,
|
||||
seq: 1,
|
||||
received: make(chan bool, 1),
|
||||
debug: false,
|
||||
}
|
||||
|
||||
go ret.readThread()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) SetSeq(s uint64) {
|
||||
r.seq = s
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) Debug(b bool) {
|
||||
r.debug = b
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) SetRootCA(s *string) {
|
||||
r.root_ca = s
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) Version() (string, error) {
|
||||
return r.Rpc_system_version()
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package rtl8720dn
|
||||
|
||||
// TODO: Implement these when needed
|
||||
// https://github.com/Seeed-Studio/seeed-ambd-firmware/blob/master/erpc_idl/erpc_shim/rpc_system_header.h
|
||||
|
||||
type RPC_T_GAP_CAUSE int32
|
||||
type RPC_T_LE_KEY_ENTRY int32
|
||||
type RPC_T_APP_RESULT int32
|
||||
type RPC_T_GAP_PARAM_TYPE int32
|
||||
|
||||
type RPC_T_LE_BOND_PARAM_TYPE int32
|
||||
type RPC_T_GAP_CFM_CAUSE int32
|
||||
type RPC_T_GAP_REMOTE_ADDR_TYPE int32
|
||||
type RPC_T_GAP_SEC_LEVEL int32
|
||||
type RPC_T_GAP_LE_PARAM_TYPE int32
|
||||
|
||||
type RPC_T_GAP_WHITE_LIST_OP int32
|
||||
type RPC_T_GAP_RAND_ADDR_TYPE int32
|
||||
type RPC_T_GAP_IDENT_ADDR_TYPE int32
|
||||
type RPC_T_GAP_CONFIG_GATT_CCCD_NOT_CHECK int32
|
||||
type RPC_T_LE_ADV_PARAM_TYPE int32
|
||||
type RPC_T_LE_SCAN_PARAM_TYPE int32
|
||||
type RPC_T_LE_CONN_PARAM_TYPE int32
|
||||
type RPC_T_GAP_CONN_INFO int32
|
||||
|
||||
type RPC_T_GAP_PHYS_OPTIONS int32
|
||||
type RPC_T_GAP_CONN_PARAM_TYPE int32
|
||||
type RPC_T_GAP_LE_CONN_REQ_PARAM int32
|
||||
type RPC_T_GAP_LOCAL_ADDR_TYPE int32
|
||||
type RPC_T_LOCAL_NAME int32
|
||||
type RPC_T_LOCAL_APPEARANCE int32
|
||||
type RPC_T_LE_CCCD int32
|
||||
|
||||
type RPC_T_LE_KEY_TYPE int32
|
||||
type RPC_T_GATT_WRITE_TYPE int32
|
||||
type RPC_T_GATT_PDU_TYPE int32
|
||||
type RPC_T_SERVICE_CALLBACK_TYPE int32
|
||||
@@ -0,0 +1,51 @@
|
||||
package rtl8720dn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type httpHeader []byte
|
||||
|
||||
func (h httpHeader) ContentLength() int {
|
||||
contentLength := -1
|
||||
idx := bytes.Index(h, []byte("Content-Length: "))
|
||||
if 0 <= idx {
|
||||
_, err := fmt.Sscanf(string(h[idx+16:]), "%d", &contentLength)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return contentLength
|
||||
}
|
||||
|
||||
// TODO: IPAddress implementation should be moved under drivers/net
|
||||
// The same implementation exists in wifinina.
|
||||
type IPAddress []byte
|
||||
|
||||
func (addr IPAddress) String() string {
|
||||
if len(addr) < 4 {
|
||||
return ""
|
||||
}
|
||||
return strconv.Itoa(int(addr[0])) + "." + strconv.Itoa(int(addr[1])) + "." + strconv.Itoa(int(addr[2])) + "." + strconv.Itoa(int(addr[3]))
|
||||
}
|
||||
|
||||
func ParseIPv4(s string) (IPAddress, error) {
|
||||
v := strings.Split(s, ".")
|
||||
v0, _ := strconv.Atoi(v[0])
|
||||
v1, _ := strconv.Atoi(v[1])
|
||||
v2, _ := strconv.Atoi(v[2])
|
||||
v3, _ := strconv.Atoi(v[3])
|
||||
return IPAddress([]byte{byte(v0), byte(v1), byte(v2), byte(v3)}), nil
|
||||
}
|
||||
|
||||
func (addr IPAddress) AsUint32() uint32 {
|
||||
if len(addr) < 4 {
|
||||
return 0
|
||||
}
|
||||
b := []byte(string(addr))
|
||||
return binary.BigEndian.Uint32(b[0:4])
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package rtl8720dn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (r *RTL8720DN) ConnectToAP(ssid string, password string) error {
|
||||
if len(ssid) == 0 || len(password) == 0 {
|
||||
return fmt.Errorf("connection failed: either ssid or password not set")
|
||||
}
|
||||
|
||||
_, err := r.Rpc_wifi_off()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = r.Rpc_wifi_on(0x00000001)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.Rpc_wifi_disconnect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
numTry := 5
|
||||
securityType := uint32(0x00400004)
|
||||
for i := 0; i < numTry; i++ {
|
||||
ret, err := r.Rpc_wifi_connect(ssid, password, securityType, -1, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ret != 0 {
|
||||
if i == numTry-1 {
|
||||
return fmt.Errorf("connection failed: rpc_wifi_connect failed")
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
_, err = r.Rpc_tcpip_adapter_dhcpc_start(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
_, err = r.Rpc_wifi_is_connected_to_ap()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RTL8720DN) GetIP() (ip, subnet, gateway IPAddress, err error) {
|
||||
ip_info := make([]byte, 12)
|
||||
_, err = r.Rpc_tcpip_adapter_get_ip_info(0, ip_info)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
ip = IPAddress(ip_info[0:4])
|
||||
subnet = IPAddress(ip_info[4:8])
|
||||
gateway = IPAddress(ip_info[8:12])
|
||||
|
||||
return ip, subnet, gateway, nil
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# SPI sdcard/mmc driver
|
||||
|
||||
This package provides the driver for sdcard/mmc with SPI connection.
|
||||
`examples/sdcard/console` shows a low-level access example.
|
||||
`examples/sdcard/tinyfs` shows an example of using fatfs to read FAT32.
|
||||
|
||||
If you use this package, you need to set `default-stack-size` in `targets/*.json`.
|
||||
For example, `targets/wioterminal.json` has the following configuration.
|
||||
|
||||
```
|
||||
{
|
||||
"inherits": ["atsamd51p19a"],
|
||||
"build-tags": ["wioterminal"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "Arduino",
|
||||
"msd-firmware-name": "firmware.uf2",
|
||||
"default-stack-size": 2048
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
package sdcard
|
||||
|
||||
import "fmt"
|
||||
|
||||
type CID struct {
|
||||
//// byte 0
|
||||
ManufacturerID byte
|
||||
//uint8_t mid; // Manufacturer ID
|
||||
//// byte 1-2
|
||||
OEMApplicationID uint16
|
||||
//char oid[2]; // OEM/Application ID
|
||||
//// byte 3-7
|
||||
ProductName string
|
||||
//char pnm[5]; // Product name
|
||||
//// byte 8
|
||||
ProductVersion string
|
||||
//unsigned prv_m : 4; // Product revision n.m
|
||||
//unsigned prv_n : 4;
|
||||
//// byte 9-12
|
||||
ProductSerialNumber uint32
|
||||
//uint32_t psn; // Product serial number
|
||||
//// byte 13
|
||||
ManufacturingYear byte
|
||||
ManufacturingMonth byte
|
||||
//unsigned mdt_year_high : 4; // Manufacturing date
|
||||
//unsigned reserved : 4;
|
||||
//// byte 14
|
||||
//unsigned mdt_month : 4;
|
||||
//unsigned mdt_year_low : 4;
|
||||
//// byte 15
|
||||
Always1 byte
|
||||
//unsigned always1 : 1;
|
||||
CRC byte
|
||||
//unsigned crc : 7;
|
||||
}
|
||||
|
||||
func NewCID(buf []byte) *CID {
|
||||
return &CID{
|
||||
ManufacturerID: buf[0],
|
||||
OEMApplicationID: (uint16(buf[0]) << 8) | uint16(buf[1]),
|
||||
ProductName: string(buf[3:8]),
|
||||
ProductVersion: fmt.Sprintf("%d.%d", (buf[8]&0xF0)>>4, buf[8]&0x0F),
|
||||
ProductSerialNumber: (uint32(buf[9]) << 24) | (uint32(buf[10]) << 16) | (uint32(buf[11]) << 8) | uint32(buf[12]),
|
||||
ManufacturingYear: (buf[13] & 0xF0) | (buf[14] & 0x0F),
|
||||
ManufacturingMonth: (buf[14] & 0xF0) >> 4,
|
||||
Always1: (buf[15] & 0x80) >> 7,
|
||||
CRC: buf[15] & 0x7F,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package sdcard
|
||||
|
||||
const (
|
||||
CMD0_GO_IDLE_STATE = 0
|
||||
CMD1_SEND_OP_CND = 1
|
||||
CMD2_ALL_SEND_CID = 2
|
||||
CMD3_SEND_RELATIVE_ADDR = 3
|
||||
CMD4_SET_DSR = 4
|
||||
CMD6_SWITCH_FUNC = 6
|
||||
CMD7_SELECT_DESELECT_CARD = 7
|
||||
CMD8_SEND_IF_COND = 8
|
||||
CMD9_SEND_CSD = 9
|
||||
CMD10_SEND_CID = 10
|
||||
CMD12_STOP_TRANSMISSION = 12
|
||||
CMD13_SEND_STATUS = 13
|
||||
CMD15_GO_INACTIVE_STATE = 15
|
||||
CMD16_SET_BLOCKLEN = 16
|
||||
CMD17_READ_SINGLE_BLOCK = 17
|
||||
CMD18_READ_MULTIPLE_BLOCK = 18
|
||||
CMD24_WRITE_BLOCK = 24
|
||||
CMD25_WRITE_MULTIPLE_BLOCK = 25
|
||||
CMD27_PROGRAM_CSD = 27
|
||||
CMD28_SET_WRITE_PROT = 28
|
||||
CMD29_CLR_WRITE_PROT = 29
|
||||
CMD30_SEND_WRITE_PROT = 30
|
||||
CMD32_ERASE_WR_BLK_START_ADDR = 32
|
||||
CMD33_ERASE_WR_BLK_END_ADDR = 33
|
||||
CMD38_ERASE = 38
|
||||
CMD42_LOCK_UNLOCK = 42
|
||||
CMD55_APP_CMD = 55
|
||||
CMD56_GEN_CMD = 56
|
||||
CMD58_READ_OCR = 58
|
||||
CMD59_CRC_ON_OFF = 59
|
||||
ACMD6_SET_BUS_WIDTH = 6
|
||||
ACMD13_SD_STATUS = 13
|
||||
ACMD22_SEND_NUM_WR_BLOCKS = 22
|
||||
ACMD23_SET_WR_BLK_ERASE_COUNT = 23
|
||||
ACMD41_SD_APP_OP_COND = 41
|
||||
ACMD42_SET_CLR_CARD_DETECT = 42
|
||||
ACMD51_SEND_SCR = 51
|
||||
ACMD18_SECURE_READ_MULTI_BLOCK = 18
|
||||
ACMD25_SECURE_WRITE_MULTI_BLOCK = 25
|
||||
ACMD26_SECURE_WRITE_MKB = 26
|
||||
ACMD38_SECURE_ERASE = 38
|
||||
ACMD43_GET_MKB = 43
|
||||
ACMD44_GET_MID = 44
|
||||
ACMD45_SET_CER_RN1 = 45
|
||||
ACMD46_SET_CER_RN2 = 46
|
||||
ACMD47_SET_CER_RES2 = 47
|
||||
ACMD48_SET_CER_RES1 = 48
|
||||
ACMD49_CHANGE_SECURE_AREA = 49
|
||||
)
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package sdcard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type CSD struct {
|
||||
CSD_STRUCTURE byte // 2 R [127:126] 0x01 : CSD Structure
|
||||
TAAC byte // 8 R [119:112] 0x0E : Data Read Access-Time-1
|
||||
NSAC byte // 8 R [111:104] 0x00 : Data Read Access-Time-2 in CLK Cycles (NSAC*100)
|
||||
TRAN_SPEED byte // 8 R [103:96] 0x5A : Max. Data Transfer Rate
|
||||
CCC uint16 // 12 R [95:84] 0x5B5 : Card Command Classes
|
||||
READ_BL_LEN byte // 4 R [83:80] 0x09 : Max. Read Data Block Length
|
||||
READ_BL_PARTIAL byte // 1 R [79:79] 0x00 : Partial Blocks for Read Allowed
|
||||
WRITE_BLK_MISALIGN byte // 1 R [78:78] 0x00 : Write Block Misalignment
|
||||
READ_BLK_MISALIGN byte // 1 R [77:77] 0x00 : Read Block Misalignment
|
||||
DSR_IMP byte // 1 R [76:76] 0x00 : DSR Implemented
|
||||
C_SIZE uint32 // 22 R [69:48] 0xXXXXXX : Device Size
|
||||
ERASE_BLK_EN byte // 1 R [46:46] 0x01 : Erase Single Block Enable
|
||||
SECTOR_SIZE byte // 7 R [45:39] 0x7F : Erase Sector Size
|
||||
WP_GRP_SIZE byte // 7 R [38:32] 0x00 : Write Protect Group Size
|
||||
WP_GRP_ENABLE byte // 1 R [31:31] 0x00 : Write Protect Group Enable
|
||||
R2W_FACTOR byte // 3 R [28:26] 0x02 : Write Speed Factor
|
||||
WRITE_BL_LEN byte // 4 R [25:22] 0x09 : Max. Write data Block Length
|
||||
WRITE_BL_PARTIAL byte // 1 R [21:21] 0x00 : Partial Blocks for Write Allowed
|
||||
FILE_FORMAT_GRP byte // 1 R [15:15] 0x00 : File Format Group
|
||||
COPY byte // 1 RW [14:14] 0x00 :Copy Flag
|
||||
PERM_WRITE_PROTECT byte // 1 RW [13:13] 0x00 : Permanent Write Protection
|
||||
TMP_WRITE_PROTECT byte // 1 RW [12:12] 0x00 : Temporary Write Protection
|
||||
FILE_FORMAT byte // 2 R [11:10] 0x00 : File Format
|
||||
CRC byte // 7 RW [7:1] 0xXX : CRC
|
||||
}
|
||||
|
||||
func NewCSD(buf []byte) *CSD {
|
||||
return &CSD{
|
||||
CSD_STRUCTURE: (buf[0] & 0xC0) >> 6,
|
||||
TAAC: buf[1],
|
||||
NSAC: buf[2],
|
||||
TRAN_SPEED: buf[3],
|
||||
CCC: uint16(buf[4])<<4 | uint16(buf[5])>>4,
|
||||
READ_BL_LEN: buf[5] & 0x0F,
|
||||
READ_BL_PARTIAL: (buf[6] & 0x80) >> 7,
|
||||
WRITE_BLK_MISALIGN: (buf[6] & 0x40) >> 6,
|
||||
READ_BLK_MISALIGN: (buf[6] & 0x20) >> 5,
|
||||
DSR_IMP: (buf[6] & 0x10) >> 4,
|
||||
C_SIZE: uint32(buf[7]&0x3F)<<16 | uint32(buf[8])<<8 | uint32(buf[9]),
|
||||
ERASE_BLK_EN: (buf[10] & 0x40) >> 6,
|
||||
SECTOR_SIZE: (buf[10]&0x3F)<<1 | (buf[11]&0x80)>>7,
|
||||
WP_GRP_SIZE: buf[11] & 0x7F,
|
||||
WP_GRP_ENABLE: (buf[12] & 0x80) >> 7,
|
||||
R2W_FACTOR: (buf[12] & 0x1C) >> 2,
|
||||
WRITE_BL_LEN: (buf[12]&0x03)<<2 | (buf[13]&0xC0)>>6,
|
||||
WRITE_BL_PARTIAL: (buf[13] & 0x20) >> 5,
|
||||
FILE_FORMAT_GRP: (buf[14] & 0x80) >> 7,
|
||||
COPY: (buf[14] & 0x40) >> 6,
|
||||
PERM_WRITE_PROTECT: (buf[14] & 0x20) >> 5,
|
||||
TMP_WRITE_PROTECT: (buf[14] & 0x10) >> 4,
|
||||
FILE_FORMAT: (buf[14] & 0x0C) >> 2,
|
||||
CRC: (buf[15] & 0xFE) >> 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CSD) Dump() {
|
||||
fmt.Printf("CSD_STRUCTURE: %X\r\n", c.CSD_STRUCTURE)
|
||||
fmt.Printf("TAAC: %X\r\n", c.TAAC)
|
||||
fmt.Printf("NSAC: %X\r\n", c.NSAC)
|
||||
fmt.Printf("TRAN_SPEED: %X\r\n", c.TRAN_SPEED)
|
||||
fmt.Printf("CCC: %X\r\n", c.CCC)
|
||||
fmt.Printf("READ_BL_LEN: %X\r\n", c.READ_BL_LEN)
|
||||
fmt.Printf("READ_BL_PARTIAL: %X\r\n", c.READ_BL_PARTIAL)
|
||||
fmt.Printf("WRITE_BLK_MISALIGN: %X\r\n", c.WRITE_BLK_MISALIGN)
|
||||
fmt.Printf("READ_BLK_MISALIGN: %X\r\n", c.READ_BLK_MISALIGN)
|
||||
fmt.Printf("DSR_IMP: %X\r\n", c.DSR_IMP)
|
||||
fmt.Printf("C_SIZE: %X\r\n", c.C_SIZE)
|
||||
fmt.Printf("ERASE_BLK_EN: %X\r\n", c.ERASE_BLK_EN)
|
||||
fmt.Printf("SECTOR_SIZE: %X\r\n", c.SECTOR_SIZE)
|
||||
fmt.Printf("WP_GRP_SIZE: %X\r\n", c.WP_GRP_SIZE)
|
||||
fmt.Printf("WP_GRP_ENABLE: %X\r\n", c.WP_GRP_ENABLE)
|
||||
fmt.Printf("R2W_FACTOR: %X\r\n", c.R2W_FACTOR)
|
||||
fmt.Printf("WRITE_BL_LEN: %X\r\n", c.WRITE_BL_LEN)
|
||||
fmt.Printf("WRITE_BL_PARTIAL: %X\r\n", c.WRITE_BL_PARTIAL)
|
||||
fmt.Printf("FILE_FORMAT_GRP: %X\r\n", c.FILE_FORMAT_GRP)
|
||||
fmt.Printf("COPY: %X\r\n", c.COPY)
|
||||
fmt.Printf("PERM_WRITE_PROTECT: %X\r\n", c.PERM_WRITE_PROTECT)
|
||||
fmt.Printf("TMP_WRITE_PROTECT: %X\r\n", c.TMP_WRITE_PROTECT)
|
||||
fmt.Printf("FILE_FORMAT: %X\r\n", c.FILE_FORMAT)
|
||||
fmt.Printf("CRC: %X\r\n", c.CRC)
|
||||
}
|
||||
|
||||
func (c *CSD) Sectors() (int64, error) {
|
||||
sectors := int64(0)
|
||||
if c.CSD_STRUCTURE == 0x01 {
|
||||
// CSD version 2.0
|
||||
sectors = (int64(c.C_SIZE) + 1) * 1024
|
||||
} else if c.CSD_STRUCTURE == 0x00 {
|
||||
// CSD version 1.0 (old, <=2GB)
|
||||
return 0, fmt.Errorf("CSD format version 1.0 is not supported")
|
||||
} else {
|
||||
return 0, fmt.Errorf("unknown CSD format")
|
||||
}
|
||||
return sectors, nil
|
||||
}
|
||||
|
||||
func (c *CSD) Size() uint64 {
|
||||
return uint64(c.C_SIZE) * 512 * 1024
|
||||
}
|
||||
@@ -0,0 +1,641 @@
|
||||
package sdcard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
_CMD_TIMEOUT = 100
|
||||
|
||||
_R1_IDLE_STATE = 1 << 0
|
||||
_R1_ERASE_RESET = 1 << 1
|
||||
_R1_ILLEGAL_COMMAND = 1 << 2
|
||||
_R1_COM_CRC_ERROR = 1 << 3
|
||||
_R1_ERASE_SEQUENCE_ERROR = 1 << 4
|
||||
_R1_ADDRESS_ERROR = 1 << 5
|
||||
_R1_PARAMETER_ERROR = 1 << 6
|
||||
|
||||
// card types
|
||||
SD_CARD_TYPE_SD1 = 1 // Standard capacity V1 SD card
|
||||
SD_CARD_TYPE_SD2 = 2 // Standard capacity V2 SD card
|
||||
SD_CARD_TYPE_SDHC = 3 // High Capacity SD card
|
||||
)
|
||||
|
||||
var (
|
||||
dummy [512]byte
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
bus machine.SPI
|
||||
sck machine.Pin
|
||||
sdo machine.Pin
|
||||
sdi machine.Pin
|
||||
cs machine.Pin
|
||||
cmdbuf []byte
|
||||
dummybuf []byte
|
||||
tokenbuf []byte
|
||||
sdCardType byte
|
||||
CID *CID
|
||||
CSD *CSD
|
||||
}
|
||||
|
||||
func New(b machine.SPI, sck, sdo, sdi, cs machine.Pin) Device {
|
||||
return Device{
|
||||
bus: b,
|
||||
cs: cs,
|
||||
sck: sck,
|
||||
sdo: sdo,
|
||||
sdi: sdi,
|
||||
cmdbuf: make([]byte, 6),
|
||||
dummybuf: make([]byte, 512),
|
||||
tokenbuf: make([]byte, 1),
|
||||
sdCardType: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Device) Configure() error {
|
||||
return d.initCard()
|
||||
}
|
||||
|
||||
func (d *Device) initCard() error {
|
||||
d.bus.Configure(machine.SPIConfig{
|
||||
SCK: d.sck,
|
||||
SDO: d.sdo,
|
||||
SDI: d.sdi,
|
||||
Frequency: 250000,
|
||||
LSBFirst: false,
|
||||
Mode: 0, // phase=0, polarity=0
|
||||
})
|
||||
|
||||
// set pin modes
|
||||
d.cs.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
d.cs.High()
|
||||
|
||||
for i := range dummy {
|
||||
dummy[i] = 0xFF
|
||||
}
|
||||
|
||||
// clock card at least 100 cycles with cs high
|
||||
d.bus.Tx(dummy[:10], nil)
|
||||
|
||||
d.cs.Low()
|
||||
d.bus.Tx(dummy[:], nil)
|
||||
|
||||
// CMD0: init card; sould return _R1_IDLE_STATE (allow 5 attempts)
|
||||
ok := false
|
||||
tm := setTimeout(0, 2*time.Second)
|
||||
for !tm.expired() {
|
||||
// Wait up to 2 seconds to be the same as the Arduino
|
||||
if d.cmd(CMD0_GO_IDLE_STATE, 0, 0x95) == _R1_IDLE_STATE {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("no SD card")
|
||||
}
|
||||
|
||||
// CMD8: determine card version
|
||||
r := d.cmd(CMD8_SEND_IF_COND, 0x01AA, 0x87)
|
||||
if (r & _R1_ILLEGAL_COMMAND) == _R1_ILLEGAL_COMMAND {
|
||||
d.sdCardType = SD_CARD_TYPE_SD1
|
||||
return fmt.Errorf("init_card_v1 not impl\r\n")
|
||||
} else {
|
||||
// r7 response
|
||||
status := byte(0)
|
||||
for i := 0; i < 3; i++ {
|
||||
var err error
|
||||
status, err = d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if (status & 0x0F) != 0x01 {
|
||||
return fmt.Errorf("SD_CARD_ERROR_CMD8 %02X", status)
|
||||
}
|
||||
|
||||
for i := 3; i < 4; i++ {
|
||||
var err error
|
||||
status, err = d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if status != 0xAA {
|
||||
return fmt.Errorf("SD_CARD_ERROR_CMD8 %02X", status)
|
||||
}
|
||||
d.sdCardType = SD_CARD_TYPE_SD2
|
||||
}
|
||||
|
||||
// initialize card and send host supports SDHC if SD2
|
||||
arg := uint32(0)
|
||||
if d.sdCardType == SD_CARD_TYPE_SD2 {
|
||||
arg = 0x40000000
|
||||
}
|
||||
|
||||
// check for timeout
|
||||
ok = false
|
||||
tm = setTimeout(0, 2*time.Second)
|
||||
for !tm.expired() {
|
||||
if d.acmd(ACMD41_SD_APP_OP_COND, arg) == 0 {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("SD_CARD_ERROR_ACMD41")
|
||||
}
|
||||
|
||||
// if SD2 read OCR register to check for SDHC card
|
||||
if d.sdCardType == SD_CARD_TYPE_SD2 {
|
||||
if d.cmd(CMD58_READ_OCR, 0, 0xFF) != 0 {
|
||||
return fmt.Errorf("SD_CARD_ERROR_CMD58")
|
||||
}
|
||||
|
||||
status, err := d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (status & 0xC0) == 0xC0 {
|
||||
d.sdCardType = SD_CARD_TYPE_SDHC
|
||||
}
|
||||
// discard rest of ocr - contains allowed voltage range
|
||||
for i := 1; i < 4; i++ {
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
}
|
||||
}
|
||||
|
||||
if d.cmd(CMD16_SET_BLOCKLEN, 0x0200, 0xFF) != 0 {
|
||||
return fmt.Errorf("SD_CARD_ERROR_CMD16")
|
||||
}
|
||||
|
||||
var buf [16]byte
|
||||
// read CID
|
||||
err := d.ReadCID(buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.CID = NewCID(buf[:])
|
||||
|
||||
// read CSD
|
||||
err = d.ReadCSD(buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.CSD = NewCSD(buf[:])
|
||||
|
||||
d.cs.High()
|
||||
|
||||
d.bus.Configure(machine.SPIConfig{
|
||||
SCK: d.sck,
|
||||
SDO: d.sdo,
|
||||
SDI: d.sdi,
|
||||
Frequency: 4000000,
|
||||
LSBFirst: false,
|
||||
Mode: 0, // phase=0, polarity=0
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d Device) acmd(cmd byte, arg uint32) byte {
|
||||
d.cmd(CMD55_APP_CMD, 0, 0xFF)
|
||||
return d.cmd(cmd, arg, 0xFF)
|
||||
}
|
||||
|
||||
func (d Device) cmd(cmd byte, arg uint32, crc byte) byte {
|
||||
d.cs.Low()
|
||||
|
||||
if cmd != 12 {
|
||||
d.waitNotBusy(300 * time.Millisecond)
|
||||
}
|
||||
|
||||
// create and send the command
|
||||
buf := d.cmdbuf
|
||||
buf[0] = 0x40 | cmd
|
||||
buf[1] = byte(arg >> 24)
|
||||
buf[2] = byte(arg >> 16)
|
||||
buf[3] = byte(arg >> 8)
|
||||
buf[4] = byte(arg)
|
||||
buf[5] = crc
|
||||
d.bus.Tx(buf, nil)
|
||||
|
||||
if cmd == 12 {
|
||||
// skip 1 byte
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
}
|
||||
|
||||
// wait for the response (response[7] == 0)
|
||||
for i := 0; i < 0xFFFF; i++ {
|
||||
d.bus.Tx([]byte{0xFF}, d.tokenbuf)
|
||||
response := d.tokenbuf[0]
|
||||
if (response & 0x80) == 0 {
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
//// timeout
|
||||
d.cs.High()
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
|
||||
return 0xFF // -1
|
||||
}
|
||||
|
||||
func (d Device) waitNotBusy(timeout time.Duration) error {
|
||||
tm := setTimeout(1, timeout)
|
||||
for !tm.expired() {
|
||||
r, err := d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r == 0xFF {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d Device) waitStartBlock() error {
|
||||
status := byte(0xFF)
|
||||
|
||||
tm := setTimeout(0, 300*time.Millisecond)
|
||||
for !tm.expired() {
|
||||
var err error
|
||||
status, err = d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
d.cs.High()
|
||||
return err
|
||||
}
|
||||
if status != 0xFF {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if status != 254 {
|
||||
d.cs.High()
|
||||
return fmt.Errorf("SD_CARD_START_BLOCK")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadCSD reads the CSD using CMD9.
|
||||
func (d Device) ReadCSD(csd []byte) error {
|
||||
return d.readRegister(CMD9_SEND_CSD, csd)
|
||||
}
|
||||
|
||||
// ReadCID reads the CID using CMD10
|
||||
func (d Device) ReadCID(csd []byte) error {
|
||||
return d.readRegister(CMD10_SEND_CID, csd)
|
||||
}
|
||||
|
||||
func (d Device) readRegister(cmd uint8, dst []byte) error {
|
||||
if d.cmd(cmd, 0, 0xFF) != 0 {
|
||||
return fmt.Errorf("SD_CARD_ERROR_READ_REG")
|
||||
}
|
||||
if err := d.waitStartBlock(); err != nil {
|
||||
return err
|
||||
}
|
||||
// transfer data
|
||||
for i := uint16(0); i < 16; i++ {
|
||||
r, err := d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst[i] = r
|
||||
}
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
d.cs.High()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadData reads 512 bytes from sdcard into dst.
|
||||
func (d Device) ReadData(block uint32, dst []byte) error {
|
||||
if len(dst) < 512 {
|
||||
return fmt.Errorf("len(dst) must be greater than or equal to 512")
|
||||
}
|
||||
|
||||
// use address if not SDHC card
|
||||
if d.sdCardType != SD_CARD_TYPE_SDHC {
|
||||
block <<= 9
|
||||
}
|
||||
if d.cmd(CMD17_READ_SINGLE_BLOCK, block, 0xFF) != 0 {
|
||||
return fmt.Errorf("CMD17 error")
|
||||
}
|
||||
if err := d.waitStartBlock(); err != nil {
|
||||
return fmt.Errorf("waitStartBlock()")
|
||||
}
|
||||
|
||||
err := d.bus.Tx(dummy[:512], dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// skip CRC (2byte)
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
|
||||
// TODO: probably not necessary
|
||||
d.cs.High()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMultiStart starts the continuous write mode using CMD25.
|
||||
func (d Device) WriteMultiStart(block uint32) error {
|
||||
// use address if not SDHC card
|
||||
if d.sdCardType != SD_CARD_TYPE_SDHC {
|
||||
block <<= 9
|
||||
}
|
||||
if d.cmd(CMD25_WRITE_MULTIPLE_BLOCK, block, 0xFF) != 0 {
|
||||
return fmt.Errorf("CMD25 error")
|
||||
}
|
||||
|
||||
// skip 1 byte
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMulti performs continuous writing. It is necessary to call
|
||||
// WriteMultiStart() in prior.
|
||||
func (d Device) WriteMulti(buf []byte) error {
|
||||
// send Data Token for CMD25
|
||||
d.bus.Transfer(byte(0xFC))
|
||||
|
||||
for i := 0; i < 512; i++ {
|
||||
_, err := d.bus.Transfer(buf[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// send dummy CRC (2 byte)
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
|
||||
// Data Resp.
|
||||
r, err := d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (r & 0x1F) != 0x05 {
|
||||
return fmt.Errorf("SD_CARD_ERROR_WRITE")
|
||||
}
|
||||
|
||||
// wait no busy
|
||||
err = d.waitNotBusy(600 * time.Millisecond)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SD_CARD_ERROR_WRITE_TIMEOUT")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMultiStop exits the continuous write mode.
|
||||
func (d Device) WriteMultiStop() error {
|
||||
defer d.cs.High()
|
||||
|
||||
// Stop Tran token for CMD25
|
||||
d.bus.Transfer(0xFD)
|
||||
|
||||
// skip 1 byte
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
|
||||
err := d.waitNotBusy(600 * time.Millisecond)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteData writes 512 bytes from dst to sdcard.
|
||||
func (d Device) WriteData(block uint32, src []byte) error {
|
||||
if len(src) < 512 {
|
||||
return fmt.Errorf("len(src) must be greater than or equal to 512")
|
||||
}
|
||||
|
||||
// use address if not SDHC card
|
||||
if d.sdCardType != SD_CARD_TYPE_SDHC {
|
||||
block <<= 9
|
||||
}
|
||||
if d.cmd(CMD24_WRITE_BLOCK, block, 0xFF) != 0 {
|
||||
return fmt.Errorf("CMD24 error")
|
||||
}
|
||||
|
||||
// wait 1 byte?
|
||||
token := byte(0xFE)
|
||||
d.bus.Transfer(token)
|
||||
|
||||
err := d.bus.Tx(src[:512], nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// send dummy CRC (2 byte)
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
d.bus.Transfer(byte(0xFF))
|
||||
|
||||
// Data Resp.
|
||||
r, err := d.bus.Transfer(byte(0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (r & 0x1F) != 0x05 {
|
||||
return fmt.Errorf("SD_CARD_ERROR_WRITE")
|
||||
}
|
||||
|
||||
// wait no busy
|
||||
err = d.waitNotBusy(600 * time.Millisecond)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SD_CARD_ERROR_WRITE_TIMEOUT")
|
||||
}
|
||||
|
||||
// TODO: probably not necessary
|
||||
d.cs.High()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadAt reads the given number of bytes from the sdcard.
|
||||
func (dev *Device) ReadAt(buf []byte, addr int64) (int, error) {
|
||||
block := uint64(addr)
|
||||
// use address if not SDHC card
|
||||
if dev.sdCardType == SD_CARD_TYPE_SDHC {
|
||||
block >>= 9
|
||||
}
|
||||
|
||||
idx := uint32(0)
|
||||
|
||||
start := uint32(addr % 512)
|
||||
end := uint32(0)
|
||||
remain := uint32(len(buf))
|
||||
|
||||
// If data starts in the middle
|
||||
if 0 < start {
|
||||
if start+remain <= 512 {
|
||||
end = start + remain
|
||||
} else {
|
||||
end = 512
|
||||
}
|
||||
|
||||
err := dev.ReadData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
copy(buf[idx:], dev.dummybuf[start:end])
|
||||
|
||||
remain -= end - start
|
||||
idx += end - start
|
||||
block++
|
||||
}
|
||||
|
||||
// If more than 512 bytes left
|
||||
for 512 <= remain {
|
||||
start = 0
|
||||
end = 512
|
||||
|
||||
err := dev.ReadData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
copy(buf[idx:], dev.dummybuf[start:end])
|
||||
|
||||
remain -= end - start
|
||||
idx += end - start
|
||||
block++
|
||||
}
|
||||
|
||||
// Read to the end
|
||||
if 0 < remain {
|
||||
start = 0
|
||||
end = remain
|
||||
|
||||
err := dev.ReadData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
copy(buf[idx:], dev.dummybuf[start:end])
|
||||
|
||||
remain -= end - start
|
||||
idx += end - start
|
||||
block++
|
||||
}
|
||||
|
||||
return int(idx), nil
|
||||
}
|
||||
|
||||
// WriteAt writes the given number of bytes to sdcard.
|
||||
func (dev *Device) WriteAt(buf []byte, addr int64) (n int, err error) {
|
||||
block := uint64(addr)
|
||||
// use address if not SDHC card
|
||||
if dev.sdCardType == SD_CARD_TYPE_SDHC {
|
||||
block >>= 9
|
||||
}
|
||||
|
||||
idx := uint32(0)
|
||||
|
||||
start := uint32(addr % 512)
|
||||
end := uint32(0)
|
||||
remain := uint32(len(buf))
|
||||
|
||||
// If data starts in the middle
|
||||
if 0 < start {
|
||||
if start+remain <= 512 {
|
||||
end = start + remain
|
||||
} else {
|
||||
end = 512
|
||||
}
|
||||
|
||||
err := dev.ReadData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
copy(dev.dummybuf[start:end], buf[idx:])
|
||||
|
||||
err = dev.WriteData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
remain -= end - start
|
||||
idx += end - start
|
||||
block++
|
||||
}
|
||||
|
||||
// If more than 512 bytes left
|
||||
for 512 <= remain {
|
||||
start = 0
|
||||
end = 512
|
||||
|
||||
err := dev.WriteData(uint32(block), buf[idx:idx+512])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
remain -= end - start
|
||||
idx += end - start
|
||||
block++
|
||||
}
|
||||
|
||||
// Write to the end
|
||||
if 0 < remain {
|
||||
start = 0
|
||||
end = remain
|
||||
|
||||
err := dev.ReadData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
copy(dev.dummybuf[start:end], buf[idx:])
|
||||
|
||||
err = dev.WriteData(uint32(block), dev.dummybuf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
remain -= end - start
|
||||
idx += end - start
|
||||
block++
|
||||
}
|
||||
|
||||
return int(idx), nil
|
||||
}
|
||||
|
||||
// Size returns the number of bytes in this sdcard.
|
||||
func (dev *Device) Size() int64 {
|
||||
return int64(dev.CSD.Size())
|
||||
}
|
||||
|
||||
// WriteBlockSize returns the block size in which data can be written to
|
||||
// memory.
|
||||
func (dev *Device) WriteBlockSize() int64 {
|
||||
return 512
|
||||
}
|
||||
|
||||
// EraseBlockSize returns the smallest erasable area on this sdcard in bytes.
|
||||
func (dev *Device) EraseBlockSize() int64 {
|
||||
return 512
|
||||
}
|
||||
|
||||
// EraseBlocks erases the given number of blocks.
|
||||
func (dev *Device) EraseBlocks(start, len int64) error {
|
||||
dev.WriteMultiStart(uint32(start))
|
||||
|
||||
for i := range dev.dummybuf {
|
||||
dev.dummybuf[i] = 0
|
||||
}
|
||||
|
||||
for i := 0; i < int(len); i++ {
|
||||
dev.WriteMulti(dev.dummybuf)
|
||||
}
|
||||
|
||||
dev.WriteMultiStop()
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package sdcard
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var timeoutTimer [2]timer
|
||||
|
||||
type timer struct {
|
||||
start int64
|
||||
timeout int64
|
||||
}
|
||||
|
||||
func setTimeout(timerID int, timeout time.Duration) *timer {
|
||||
timeoutTimer[timerID].start = time.Now().UnixNano()
|
||||
timeoutTimer[timerID].timeout = timeout.Nanoseconds()
|
||||
return &timeoutTimer[timerID]
|
||||
}
|
||||
|
||||
func (t timer) expired() bool {
|
||||
return time.Now().UnixNano() > (t.start + t.timeout)
|
||||
}
|
||||
+1
-1
@@ -2,4 +2,4 @@ package drivers
|
||||
|
||||
// Version returns a user-readable string showing the version of the drivers package for support purposes.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.16.0"
|
||||
const Version = "0.17.1"
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
package wifinina
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -104,7 +104,7 @@ func (drv *Driver) connectSocket(addr, portStr string, mode uint8) error {
|
||||
func convertPort(portStr string) (uint16, error) {
|
||||
p64, err := strconv.ParseUint(portStr, 10, 16)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not convert port to uint16: %w", err)
|
||||
return 0, errors.New("could not convert port to uint16: " + err.Error())
|
||||
}
|
||||
return uint16(p64), nil
|
||||
}
|
||||
@@ -175,13 +175,13 @@ func (drv *Driver) Write(b []byte) (n int, err error) {
|
||||
}
|
||||
if drv.proto == ProtoModeUDP {
|
||||
if err := drv.dev.StartClient("", drv.ip, drv.port, drv.sock, drv.proto); err != nil {
|
||||
return 0, fmt.Errorf("error in startClient: %w", err)
|
||||
return 0, errors.New("error in startClient: " + err.Error())
|
||||
}
|
||||
if _, err := drv.dev.InsertDataBuf(b, drv.sock); err != nil {
|
||||
return 0, fmt.Errorf("error in insertDataBuf: %w", err)
|
||||
return 0, errors.New("error in insertDataBuf: " + err.Error())
|
||||
}
|
||||
if _, err := drv.dev.SendUDPData(drv.sock); err != nil {
|
||||
return 0, fmt.Errorf("error in sendUDPData: %w", err)
|
||||
return 0, errors.New("error in sendUDPData: " + err.Error())
|
||||
}
|
||||
return len(b), nil
|
||||
} else {
|
||||
|
||||
+24
-10
@@ -8,7 +8,10 @@ package wifinina // import "tinygo.org/x/drivers/wifinina"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"encoding/hex"
|
||||
"fmt" // used only in debug printouts and is optimized out when debugging is disabled
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"machine"
|
||||
@@ -213,15 +216,16 @@ func (addr IPAddress) String() string {
|
||||
if len(addr) < 4 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3])
|
||||
return strconv.Itoa(int(addr[0])) + "." + strconv.Itoa(int(addr[1])) + "." + strconv.Itoa(int(addr[2])) + "." + strconv.Itoa(int(addr[3]))
|
||||
}
|
||||
|
||||
func ParseIPv4(s string) (IPAddress, error) {
|
||||
var v0, v1, v2, v3 uint8
|
||||
if _, err := fmt.Sscanf(s, "%d.%d.%d.%d", &v0, &v1, &v2, &v3); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return IPAddress([]byte{v0, v1, v2, v3}), nil
|
||||
v := strings.Split(s, ".")
|
||||
v0, _ := strconv.Atoi(v[0])
|
||||
v1, _ := strconv.Atoi(v[1])
|
||||
v2, _ := strconv.Atoi(v[2])
|
||||
v3, _ := strconv.Atoi(v[3])
|
||||
return IPAddress([]byte{byte(v0), byte(v1), byte(v2), byte(v3)}), nil
|
||||
}
|
||||
|
||||
func (addr IPAddress) AsUint32() uint32 {
|
||||
@@ -235,13 +239,23 @@ func (addr IPAddress) AsUint32() uint32 {
|
||||
type MACAddress uint64
|
||||
|
||||
func (addr MACAddress) String() string {
|
||||
return fmt.Sprintf("%016X", uint64(addr))
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, uint64(addr))
|
||||
encoded := hex.EncodeToString(b)
|
||||
result := ""
|
||||
for i := 2; i < 8; i++ {
|
||||
result += encoded[i*2 : i*2+2]
|
||||
if i < 7 {
|
||||
result += ":"
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type Error uint8
|
||||
|
||||
func (err Error) Error() string {
|
||||
return fmt.Sprintf("wifinina error: 0x%02X", uint8(err))
|
||||
return "wifinina error: 0x" + hex.EncodeToString([]byte{uint8(err)})
|
||||
}
|
||||
|
||||
// Cmd Struct Message */
|
||||
@@ -484,7 +498,7 @@ func (d *Device) GetCurrentBSSID() (MACAddress, error) {
|
||||
}
|
||||
|
||||
func (d *Device) GetCurrentRSSI() (int32, error) {
|
||||
return d.getInt32(d.req1(CmdGetCurrBSSID))
|
||||
return d.getInt32(d.req1(CmdGetCurrRSSI))
|
||||
}
|
||||
|
||||
func (d *Device) GetCurrentSSID() (string, error) {
|
||||
|
||||
@@ -7,6 +7,7 @@ package ws2812
|
||||
import (
|
||||
"device/avr"
|
||||
"machine"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Send a single byte using the WS2812 protocol.
|
||||
@@ -17,6 +18,7 @@ func (d Device) WriteByte(c byte) error {
|
||||
// Probably this is about pointer registers, which are very limited on AVR.
|
||||
port, maskSet := d.Pin.PortMaskSet()
|
||||
_, maskClear := d.Pin.PortMaskClear()
|
||||
mask := interrupt.Disable()
|
||||
|
||||
switch machine.CPUFrequency() {
|
||||
case 16e6: // 16MHz
|
||||
@@ -51,8 +53,10 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": port,
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
default:
|
||||
interrupt.Restore(mask)
|
||||
return errUnknownClockSpeed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package ws2812
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Send a single byte using the WS2812 protocol.
|
||||
@@ -14,6 +15,7 @@ func (d Device) WriteByte(c byte) error {
|
||||
// For the Cortex-M0 at 16MHz
|
||||
portSet, maskSet := d.Pin.PortMaskSet()
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
mask := interrupt.Disable()
|
||||
|
||||
// See:
|
||||
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
|
||||
@@ -48,5 +50,6 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": portClear,
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package ws2812
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Send a single byte using the WS2812 protocol.
|
||||
@@ -14,6 +15,7 @@ func (d Device) WriteByte(c byte) error {
|
||||
// For the Cortex-M0 at 48MHz
|
||||
portSet, maskSet := d.Pin.PortMaskSet()
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
mask := interrupt.Disable()
|
||||
|
||||
// See:
|
||||
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
|
||||
@@ -77,5 +79,6 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": portClear,
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build atsamd51
|
||||
// +build atsamd51 atsame5x
|
||||
|
||||
package ws2812
|
||||
|
||||
@@ -8,6 +8,7 @@ package ws2812
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Send a single byte using the WS2812 protocol.
|
||||
@@ -15,6 +16,7 @@ func (d Device) WriteByte(c byte) error {
|
||||
// For the Cortex-M4 at 120MHz
|
||||
portSet, maskSet := d.Pin.PortMaskSet()
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
mask := interrupt.Disable()
|
||||
|
||||
// See:
|
||||
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
|
||||
@@ -169,5 +171,6 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": portClear,
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build nrf52 nrf52840
|
||||
// +build nrf52 nrf52840 nrf52833
|
||||
|
||||
package ws2812
|
||||
|
||||
@@ -7,6 +7,7 @@ package ws2812
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Send a single byte using the WS2812 protocol.
|
||||
@@ -14,6 +15,7 @@ func (d Device) WriteByte(c byte) error {
|
||||
// For the Cortex-M4 at 64MHz
|
||||
portSet, maskSet := d.Pin.PortMaskSet()
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
mask := interrupt.Disable()
|
||||
|
||||
// See:
|
||||
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
|
||||
@@ -106,5 +108,6 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": portClear,
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ package ws2812
|
||||
import (
|
||||
"device"
|
||||
"machine"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (d Device) WriteByte(c byte) error {
|
||||
portSet, maskSet := d.Pin.PortMaskSet()
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
mask := interrupt.Disable()
|
||||
|
||||
switch machine.CPUFrequency() {
|
||||
case 160e6: // 160MHz
|
||||
@@ -220,6 +222,7 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": uintptr(unsafe.Pointer(portClear)),
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
case 80e6: // 80MHz
|
||||
// See docs for 160MHz.
|
||||
@@ -336,8 +339,10 @@ func (d Device) WriteByte(c byte) error {
|
||||
"maskClear": maskClear,
|
||||
"portClear": uintptr(unsafe.Pointer(portClear)),
|
||||
})
|
||||
interrupt.Restore(mask)
|
||||
return nil
|
||||
default:
|
||||
interrupt.Restore(mask)
|
||||
return errUnknownClockSpeed
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user