Compare commits

...

16 Commits

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

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

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

Tested on Arduino Nano RP2040 Connect.  Also tried testing on Arduino
Nano33 IoT but test panics with "out of memory".  There's only 32K of
SRAM on the Nano33, vs 264K on the rp2040 Connect.
2022-11-14 22:24:15 +01:00
93 changed files with 908 additions and 230 deletions
+3 -3
View File
@@ -112,7 +112,7 @@ The following 90 devices are supported.
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
| [QMI8658C accelerometer/gyroscope](https://www.qstcorp.com/upload/pdf/202202/%EF%BC%88%E5%B7%B2%E4%BC%A0%EF%BC%89QMI8658C%20datasheet%20rev%200.9.pdf) | I2C |
| [QMI8658C accelerometer/gyroscope](https://www.qstcorp.com/upload/pdf/202202/%EF%BC%88%E5%B7%B2%E4%BC%A0%EF%BC%89QMI8658C%20datasheet%20rev%200.9.pdf) | I2C |
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
| [RTL8720DN 2.4G/5G Dual Bands Wireless and BLE5.0](https://www.seeedstudio.com/Realtek8720DN-2-4G-5G-Dual-Bands-Wireless-and-BLE5-0-Combo-Module-p-4442.html) | UART |
| [SCD4x CO2 Sensor](https://sensirion.com/media/documents/C4B87CE6/627C2DCD/CD_DS_SCD40_SCD41_Datasheet_D1.pdf) | I2C |
@@ -141,10 +141,10 @@ The following 90 devices are supported.
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 2.9" e-paper display (V1)](https://www.waveshare.com/w/upload/e/e6/2.9inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI |
| [Waveshare GC9A01 TFT round display](https://www.waveshare.com/w/upload/5/5e/GC9A01A.pdf) | SPI |
| [Waveshare GC9A01 TFT round display](https://www.waveshare.com/w/upload/5/5e/GC9A01A.pdf) | SPI |
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-transceiv-ers/sx1261) | SPI |
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-connect/sx1261) | SPI |
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
## Contributing
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package apds9960
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
package apds9960
+115 -5
View File
@@ -7,6 +7,7 @@ package bme280
import (
"math"
"time"
"tinygo.org/x/drivers"
)
@@ -33,11 +34,27 @@ type calibrationCoefficients struct {
h6 int8
}
type Oversampling byte
type Mode byte
type FilterCoefficient byte
type Period byte
// Config contains settings for filtering, sampling, and modes of operation
type Config struct {
Pressure Oversampling
Temperature Oversampling
Humidity Oversampling
Period Period
Mode Mode
IIR FilterCoefficient
}
// Device wraps an I2C connection to a BME280 device.
type Device struct {
bus drivers.I2C
Address uint16
calibrationCoefficients calibrationCoefficients
Config Config
}
// New creates a new BME280 connection. The I2C bus must already be
@@ -51,9 +68,34 @@ func New(bus drivers.I2C) Device {
}
}
// Configure sets up the device for communication and
// read the calibration coefficientes.
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration is the Indoor Navigation settings
// from the BME280 datasheet.
func (d *Device) Configure() {
d.ConfigureWithSettings(Config{})
}
// ConfigureWithSettings sets up the device for communication and
// read the calibration coefficients.
//
// The default configuration if config is left at defaults is
// the Indoor Navigation settings from the BME280 datasheet.
func (d *Device) ConfigureWithSettings(config Config) {
d.Config = config
// If config is not initialized, use Indoor Navigation defaults.
if d.Config == (Config{}) {
d.Config = Config{
Mode: ModeNormal,
Period: Period0_5ms,
Temperature: Sampling2X,
Humidity: Sampling1X,
Pressure: Sampling16X,
IIR: Coeff16,
}
}
var data [24]byte
err := d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION, data[:])
@@ -93,10 +135,18 @@ func (d *Device) Configure() {
d.calibrationCoefficients.h4 = 0 + (int16(h2lsb[3]) << 4) | (int16(h2lsb[4] & 0x0F))
d.calibrationCoefficients.h5 = 0 + (int16(h2lsb[5]) << 4) | (int16(h2lsb[4]) >> 4)
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{0x3f})
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{0xB7})
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{0x00})
d.Reset()
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{byte(d.Config.Period<<5) | byte(d.Config.IIR<<2)})
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{byte(d.Config.Humidity)})
// Normal mode, start measuring now
if d.Config.Mode == ModeNormal {
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
}
// Connected returns whether a BME280 has been found.
@@ -112,6 +162,20 @@ func (d *Device) Reset() {
d.bus.WriteRegister(uint8(d.Address), CMD_RESET, []byte{0xB6})
}
// SetMode can set the device to Sleep, Normal or Forced mode
//
// Calling this method is optional, Configure can be used to set the
// initial mode if no mode change is desired. This method is most
// useful to switch between Sleep and Normal modes.
func (d *Device) SetMode(mode Mode) {
d.Config.Mode = mode
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d *Device) ReadTemperature() (int32, error) {
data, err := d.readData()
@@ -186,6 +250,16 @@ func readIntLE(msb byte, lsb byte) int16 {
// readData does a burst read from 0xF7 to 0xF0 according to the datasheet
// resulting in an slice with 8 bytes 0-2 = pressure / 3-5 = temperature / 6-7 = humidity
func (d *Device) readData() (data [8]byte, err error) {
if d.Config.Mode == ModeForced {
// Write the CTRL_MEAS register to trigger a measurement
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{
byte(d.Config.Temperature<<5) |
byte(d.Config.Pressure<<2) |
byte(d.Config.Mode)})
time.Sleep(d.measurementDelay())
}
err = d.bus.ReadRegister(uint8(d.Address), REG_PRESSURE, data[:])
if err != nil {
println(err)
@@ -256,3 +330,39 @@ func (d *Device) calculateHumidity(data [8]byte, tFine int32) int32 {
return int32(100 * h)
}
// measurementDelay returns how much time each measurement will take
// on the device.
//
// This is used in forced mode to wait until a measurement is complete.
func (d *Device) measurementDelay() time.Duration {
const MeasOffset = 1250
const MeasDur = 2300
const HumMeasOffset = 575
const MeasScalingFactor = 1000
// delay is based on over-sampling rate - this table converts from
// setting to number samples
sampleRateConv := []int{0, 1, 2, 4, 8, 16}
tempOsr := 16
if d.Config.Temperature <= Sampling16X {
tempOsr = sampleRateConv[d.Config.Temperature]
}
presOsr := 16
if d.Config.Temperature <= Sampling16X {
presOsr = sampleRateConv[d.Config.Pressure]
}
humOsr := 16
if d.Config.Temperature <= Sampling16X {
humOsr = sampleRateConv[d.Config.Humidity]
}
max_delay := ((MeasOffset + (MeasDur * tempOsr) +
((MeasDur * presOsr) + HumMeasOffset) +
((MeasDur * humOsr) + HumMeasOffset)) / MeasScalingFactor)
return time.Duration(max_delay) * time.Millisecond
}
+44
View File
@@ -20,6 +20,50 @@ const (
CHIP_ID = 0x60
)
// Increasing sampling rate increases precision but also the wait time for measurements. The datasheet has a table of
// suggested values for oversampling, output data rates, and iir filter coefficients by use case.
const (
SamplingOff Oversampling = iota
Sampling1X
Sampling2X
Sampling4X
Sampling8X
Sampling16X
)
// In normal mode (the default) the sensor takes masurements periodically. In forced
// mode, the sensor takes a measurement only when requested.
//
// For use-cases with infrequent sampling, forced mode is more power efficient.
const (
ModeNormal Mode = 0x03
ModeForced Mode = 0x01
ModeSleep Mode = 0x00
)
// IIR filter coefficients, higher values means steadier measurements but slower reaction times
const (
Coeff0 FilterCoefficient = iota
Coeff2
Coeff4
Coeff8
Coeff16
)
// Period of standby in normal mode which controls how often measurements are taken
//
// Note Period10ms and Period20ms are out of sequence, but are per the datasheet
const (
Period0_5ms Period = 0b000
Period62_5ms = 0b001
Period125ms = 0b010
Period250ms = 0b011
Period500ms = 0b100
Period1000ms = 0b101
Period10ms = 0b110
Period20ms = 0b111
)
const (
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
)
+6
View File
@@ -54,6 +54,12 @@ func (l *Device) Tone(hz, duration float64) (err error) {
tempo := ((60 / l.BPM) * (duration * 1000))
// no tone during rest, just let the duration pass.
if hz == Rest {
time.Sleep(time.Duration(tempo) * time.Millisecond)
return
}
for i := 0.0; i < tempo*1000; i += tone * 2.0 {
if err = l.On(); err != nil {
return
+3 -3
View File
@@ -1,9 +1,9 @@
package buzzer
const (
Whole = 4
Half = 2
Quarter = 1
Whole = 4.0
Half = 2.0
Quarter = 1.0
Eighth = 0.500
)
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
-1
View File
@@ -1,5 +1,4 @@
//go:build mimxrt1062 || stm32f405 || atsamd51 || stm32f103xx || k210 || stm32f407
// +build mimxrt1062 stm32f405 atsamd51 stm32f103xx k210 stm32f407
package dht // import "tinygo.org/x/drivers/dht"
-1
View File
@@ -1,5 +1,4 @@
//go:build !mimxrt1062 && !stm32f405 && !atsamd51 && !stm32f103xx && !k210 && !stm32f407
// +build !mimxrt1062,!stm32f405,!atsamd51,!stm32f103xx,!k210,!stm32f407
package dht // import "tinygo.org/x/drivers/dht"
+3 -3
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
@@ -11,6 +10,7 @@ package dht // import "tinygo.org/x/drivers/dht"
import (
"machine"
"runtime/interrupt"
"time"
)
@@ -160,8 +160,8 @@ func (t *device) read() error {
// interrupts
func receiveSignals(pin machine.Pin, result []counter) {
i := uint8(0)
machine.UART1.Interrupt.Disable()
defer machine.UART1.Interrupt.Enable()
mask := interrupt.Disable()
defer interrupt.Restore(mask)
for ; i < 40; i++ {
result[i*2] = expectChange(pin, false)
result[i*2+1] = expectChange(pin, true)
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
// Package dht provides a driver for DHTXX family temperature and humidity sensors.
//
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
package dht // import "tinygo.org/x/drivers/dht"
-1
View File
@@ -1,5 +1,4 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
@@ -1,5 +1,4 @@
//go:build m5stack_core2
// +build m5stack_core2
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21
// +build atsamd21
package initdisplay
-1
View File
@@ -1,5 +1,4 @@
//go:build feather_m0 || feather_m4 || feather_m4_can || feather_nrf52840 || feather_nrf52840_sense || feather_stm32f405 || feather_rp2040
// +build feather_m0 feather_m4 feather_m4_can feather_nrf52840 feather_nrf52840_sense feather_stm32f405 feather_rp2040
package initdisplay
-1
View File
@@ -1,5 +1,4 @@
//go:build m5stack
// +build m5stack
package initdisplay
@@ -1,5 +1,4 @@
//go:build m5stack_core2
// +build m5stack_core2
package initdisplay
-1
View File
@@ -1,5 +1,4 @@
//go:build pyportal
// +build pyportal
package initdisplay
@@ -1,5 +1,4 @@
//go:build wioterminal
// +build wioterminal
package initdisplay
+1 -3
View File
@@ -100,9 +100,7 @@ func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(), nil
}
-1
View File
@@ -1,5 +1,4 @@
//go:build feather_m4 || feather_m4_can || feather_nrf52840
// +build feather_m4 feather_m4_can feather_nrf52840
package main
@@ -1,5 +1,4 @@
//go:build grandcentral_m4
// +build grandcentral_m4
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21 && !p1am_100
// +build atsamd21,!p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build p1am_100
// +build p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pygamer
// +build pygamer
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pyportal
// +build pyportal
package main
@@ -1,5 +1,4 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build wioterminal
// +build wioterminal
package main
@@ -1,5 +1,4 @@
//go:build tinygo
// +build tinygo
package console
-1
View File
@@ -1,5 +1,4 @@
//go:build feather_m4 || feather_m4_can || feather_nrf52840
// +build feather_m4 feather_m4_can feather_nrf52840
package main
@@ -1,5 +1,4 @@
//go:build grandcentral_m4
// +build grandcentral_m4
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21 && !p1am_100
// +build atsamd21,!p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build p1am_100
// +build p1am_100
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pygamer
// +build pygamer
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build pyportal
// +build pyportal
package main
@@ -1,5 +1,4 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build wioterminal
// +build wioterminal
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build gnse
// +build gnse
/*
Generic Node Sensor Edition
-1
View File
@@ -1,5 +1,4 @@
//go:build lorae5
// +build lorae5
package radio
-1
View File
@@ -1,5 +1,4 @@
//go:build nucleowl55jc
// +build nucleowl55jc
/*
Nucleo WL55JC1
-1
View File
@@ -1,5 +1,4 @@
//go:build espat
// +build espat
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build rtl8720dn
// +build rtl8720dn
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build wifinina
// +build wifinina
package main
+1 -3
View File
@@ -111,9 +111,7 @@ func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(), nil
}
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_rp2040
// +build nano_rp2040
// This examples shows how to control RGB LED connected to
// NINA-W102 chip on Arduino Nano RP2040 Connect board
+209
View File
@@ -0,0 +1,209 @@
package main
import (
"fmt"
"machine"
"strconv"
"time"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/wifinina"
)
// You can override the settings with the init() in another source code:
//
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// }
//
// Or use -ldflags option on tinygo command to set at compile-time:
//
// tinygo flash ... -ldflags '-X "main.ssid=xxx" -X "main.pass=xxx"' ...
//
var (
ssid string
pass string
)
var led = machine.LED
func main() {
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
spi := machine.NINA_SPI
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor := wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, subnet, gateway, err := adaptor.GetIP()
if err != nil {
return err
}
fmt.Printf("IP Address : %s\r\n", ip)
fmt.Printf("Mask : %s\r\n", subnet)
fmt.Printf("Gateway : %s\r\n", gateway)
http.UseDriver(adaptor)
http.HandleFunc("/", root)
http.HandleFunc("/hello", hello)
http.HandleFunc("/cnt", cnt)
http.HandleFunc("/6", sixlines)
http.HandleFunc("/off", LED_OFF)
http.HandleFunc("/on", LED_ON)
return http.ListenAndServe(":80", nil)
}
func root(w http.ResponseWriter, r *http.Request) {
access := 1
cookie, err := r.Cookie("access")
if err != nil {
if err == http.ErrNoCookie {
cookie = &http.Cookie{
Name: "access",
Value: "1",
}
} else {
http.Error(w, fmt.Sprintf("%s", err.Error()), http.StatusBadRequest)
return
}
} else {
v, err := strconv.ParseInt(cookie.Value, 10, 0)
if err != nil {
http.Error(w, fmt.Sprintf("invalid cookie.Value : %s", cookie.Value), http.StatusBadRequest)
return
}
cookie.Value = fmt.Sprintf("%d", v+1)
access = int(v) + 1
}
http.SetCookie(w, cookie)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `
<html>
<head>
<title>TinyGo HTTP Server</title>
<script language="javascript" type="text/javascript">
var counter = 0
function ledOn() { fetch("/on"); }
function ledOff() { fetch("/off"); }
function fetchCnt() { fetch("/cnt").then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); }
function incrCnt() { counter = counter + 1; fetch("/cnt?cnt=" + counter, { method: 'POST' }).then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); }
function setCnt() { fetch("/cnt", {
method: "POST",
body: "cnt=" + document.getElementsByName("cnt")[0].value,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}).then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); return false; }
function onLoad() { fetchCnt(); }
</script>
</head>
<body onLoad="onLoad()">
<h5>TinyGo HTTP Server</h5>
<p>
access: %d
</p>
<a href="/hello">/hello</a><br>
<a href="/6">/6</a><br>
<p>
LED<br>
<a href="javascript:ledOn();">/on</a><br>
<a href="javascript:ledOff();">/off</a><br>
</p>
<p>
<a href="/cnt">/cnt</a><br>
cnt: <span id="cnt"></span><br>
<a href="javascript:incrCnt()">incrCnt()</a><br>
<form id="form1" style="display: inline" onSubmit="return setCnt()">
<input type="text" name="cnt">
<input type="button" value="set cnt", onClick="setCnt()">
</form>
</p>
</body>
</html>
`, access)
}
func sixlines(w http.ResponseWriter, r *http.Request) {
// https://fukuno.jig.jp/3267
fmt.Fprint(w, `<body onload='onkeydown=e=>K=parseInt(e.key[5]||6,28)/3-8;Z=X=[B=A=12];Y=_=>`+
`{for(C=[q=c=i=4];f=i--*K;c-=!Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)])p=B[i];for(c?0:K+6?h+=K:B=C;`+
`i=K=q--;f+=Z[A+p])X[p=h+B[q]]=1;h+=A;if(f|B)for(Z=X,X=[l=228],B=[[-7,-20,6,h=17,-9,3,3][t=++t%7]-4,0,1,t-6?-A:2];l--;)`+
`for(l%A?l-=l%A*!Z[l]:(P++,c=l+=A);--c>A;)Z[c]=Z[c-A];for(S="";i<240;S+=X[i]|(X[i]=Z[i]|=++i%A<2|i>228)?i%A?"■":"■<br>":" ");`+
`D.innerHTML=S+P;setTimeout(Y,i-P)};Y(h=K=t=P=0)'id=D>`)
}
func LED_ON(w http.ResponseWriter, r *http.Request) {
led.High()
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "led.High()")
}
func LED_OFF(w http.ResponseWriter, r *http.Request) {
led.Low()
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "led.Low()")
}
func hello(w http.ResponseWriter, r *http.Request) {
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "hello")
}
var counter int
func cnt(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if r.Method == "POST" {
c := r.Form.Get("cnt")
if c != "" {
i64, _ := strconv.ParseInt(c, 0, 0)
counter = int(i64)
}
}
w.Header().Set(`Content-Type`, `application/json`)
fmt.Fprintf(w, `{"cnt": %d}`, counter)
}
func message(msg string) {
println(msg, "\r")
}
-1
View File
@@ -1,5 +1,4 @@
//go:build arduino
// +build arduino
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build digispark
// +build digispark
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build !digispark && !arduino && !qtpy && !m5stamp_c3 && !thingplus_rp2040
// +build !digispark,!arduino,!qtpy,!m5stamp_c3,!thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build qtpy || m5stamp_c3
// +build qtpy m5stamp_c3
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build qtpy
// +build qtpy
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51
// +build atsamd51
package flash
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package hts221
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
package hts221
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51 || atsame5x
// +build atsamd51 atsame5x
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build esp32
// +build esp32
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build nrf52840
// +build nrf52840
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build !esp32 && !atsamd51 && !atsame5x && !stm32f4 && !rp2040 && !nrf52840
// +build !esp32,!atsamd51,!atsame5x,!stm32f4,!rp2040,!nrf52840
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build rp2040
// +build rp2040
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build stm32f4
// +build stm32f4
package i2csoft
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51
// +build atsamd51
package ili9341
-1
View File
@@ -1,5 +1,4 @@
//go:build !atsamd51 && !atsame5x && !atsamd21
// +build !atsamd51,!atsame5x,!atsamd21
package ili9341
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd21
// +build atsamd21
package ili9341
-1
View File
@@ -1,5 +1,4 @@
//go:build atsamd51 || atsame5x
// +build atsamd51 atsame5x
package ili9341
-1
View File
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
-1
View File
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build gofuzz
// +build gofuzz
package png
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package lps22hb
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
package lps22hb
-1
View File
@@ -1,5 +1,4 @@
//go:build !xiao_ble
// +build !xiao_ble
package lsm6ds3tr
-1
View File
@@ -1,5 +1,4 @@
//go:build xiao_ble
// +build xiao_ble
package lsm6ds3tr
-1
View File
@@ -1,5 +1,4 @@
//go:build !nano_33_ble
// +build !nano_33_ble
package lsm9ds1
-1
View File
@@ -1,5 +1,4 @@
//go:build nano_33_ble
// +build nano_33_ble
// Nano 33 BLE [Sense] has LSM9DS1 unit on-board.
// This custom Configure function powers unit up
-1
View File
@@ -1,5 +1,4 @@
//go:build microbit
// +build microbit
// Package microbitmatrix implements a driver for the BBC micro:bit's LED matrix.
//
-1
View File
@@ -1,5 +1,4 @@
//go:build microbit_v2
// +build microbit_v2
// Package microbitmatrix implements a driver for the BBC micro:bit version 2 LED matrix.
//
+40
View File
@@ -2,6 +2,8 @@ package http
import (
"io"
"net/url"
"strings"
"time"
)
@@ -211,3 +213,41 @@ func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response,
req.Header.Set("Content-Type", contentType)
return c.Do(req)
}
// PostForm issues a POST to the specified URL, with data's keys and
// values URL-encoded as the request body.
//
// The Content-Type header is set to application/x-www-form-urlencoded.
// To set other headers, use NewRequest and DefaultClient.Do.
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
//
// PostForm is a wrapper around DefaultClient.PostForm.
//
// See the Client.Do method documentation for details on how redirects
// are handled.
//
// To make a request with a specified context.Context, use NewRequestWithContext
// and DefaultClient.Do.
func PostForm(url string, data url.Values) (resp *Response, err error) {
return DefaultClient.PostForm(url, data)
}
// PostForm issues a POST to the specified URL,
// with data's keys and values URL-encoded as the request body.
//
// The Content-Type header is set to application/x-www-form-urlencoded.
// To set other headers, use NewRequest and Client.Do.
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
//
// See the Client.Do method documentation for details on how redirects
// are handled.
//
// To make a request with a specified context.Context, use NewRequestWithContext
// and Client.Do.
func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
+140 -123
View File
@@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"io"
"net/textproto"
"strconv"
"strings"
"time"
@@ -25,17 +26,43 @@ func (c *Client) Do(req *Request) (*Response, error) {
req.AddCookie(cookie)
}
}
transport := c.Transport
if transport == nil {
transport = DefaultTransport
}
res, err := transport.RoundTrip(req)
if c.Jar != nil {
if rc := res.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
}
}
return res, err
}
type Transport struct {
}
var DefaultTransport RoundTripper
func init() {
DefaultTransport = &Transport{}
}
func (t *Transport) RoundTrip(req *Request) (*Response, error) {
switch req.URL.Scheme {
case "http":
return c.doHTTP(req)
return t.doHTTP(req)
case "https":
return c.doHTTPS(req)
return t.doHTTPS(req)
default:
return nil, fmt.Errorf("invalid schemer : %s", req.URL.Scheme)
}
}
func (c *Client) doHTTP(req *Request) (*Response, error) {
func (t *Transport) doHTTP(req *Request) (*Response, error) {
// make TCP connection
ip := net.ParseIP(req.URL.Hostname())
port := 80
@@ -106,10 +133,10 @@ func (c *Client) doHTTP(req *Request) (*Response, error) {
}
return c.doResp(conn, req)
return t.doResp(conn, req)
}
func (c *Client) doHTTPS(req *Request) (*Response, error) {
func (t *Transport) doHTTPS(req *Request) (*Response, error) {
conn, err := tls.Dial("tcp", req.URL.Host, nil)
retry := 0
for ; err != nil; conn, err = tls.Dial("tcp", req.URL.Host, nil) {
@@ -167,141 +194,131 @@ func (c *Client) doHTTPS(req *Request) (*Response, error) {
}
return c.doResp(conn, req)
return t.doResp(conn, req)
}
func (c *Client) doResp(conn net.Conn, req *Request) (*Response, error) {
func (t *Transport) doResp(conn net.Conn, req *Request) (*Response, error) {
resp := &Response{
Header: map[string][]string{},
}
// Header
var scanner *bufio.Scanner
cont := true
ofs := 0
remain := int64(0)
for cont {
for n, err := conn.Read(buf[ofs:]); n > 0; n, err = conn.Read(buf[ofs:]) {
if err != nil {
println("Read error: " + err.Error())
} else {
// Take care of the case where "\r\n\r\n" is on the boundary of a buffer
start := ofs
if start > 3 {
start -= 3
}
idx := bytes.Index(buf[start:ofs+n], []byte("\r\n\r\n"))
if idx == -1 {
ofs += n
continue
}
idx += start + 4
br := bufio.NewReader(conn)
tp := textproto.NewReader(br)
scanner = bufio.NewScanner(bytes.NewReader(buf[0 : ofs+n]))
if resp.Status == "" && scanner.Scan() {
status := strings.SplitN(scanner.Text(), " ", 2)
if len(status) != 2 {
conn.Close()
return nil, fmt.Errorf("invalid status : %q", scanner.Text())
}
resp.Proto = status[0]
fmt.Sscanf(status[0], "HTTP/%d.%d", &resp.ProtoMajor, &resp.ProtoMinor)
resp.Status = status[1]
fmt.Sscanf(status[1], "%d", &resp.StatusCode)
}
for scanner.Scan() {
text := scanner.Text()
if text == "" {
// end of header
if idx < n+ofs {
ofs = ofs + n - idx
for i := 0; i < ofs; i++ {
buf[i] = buf[i+idx]
}
} else {
ofs = 0
}
break
} else {
header := strings.SplitN(text, ": ", 2)
if len(header) != 2 {
conn.Close()
return nil, fmt.Errorf("invalid header : %q", text)
}
if resp.Header.Get(header[0]) == "" {
resp.Header.Set(header[0], header[1])
} else {
resp.Header.Add(header[0], header[1])
}
if strings.ToLower(header[0]) == "content-length" {
resp.ContentLength, err = strconv.ParseInt(header[1], 10, 64)
if err != nil {
conn.Close()
return nil, err
}
remain = resp.ContentLength
}
}
}
cont = false
break
}
}
}
// Body
remain -= int64(ofs)
if remain <= 0 {
resp.Body = io.NopCloser(bytes.NewReader(buf[:ofs]))
if c.Jar != nil {
if rc := resp.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
}
}
return resp, conn.Close()
}
cont = true
lastRequestTime := time.Now()
for cont {
for {
end := ofs + 0x400
if len(buf) < end {
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", end)
}
n, err := conn.Read(buf[ofs : ofs+0x400])
if err != nil {
return nil, err
}
if n == 0 {
for {
line, err := tp.ReadLine()
if err != nil {
if err == io.ErrNoProgress {
// default: no timeout
continue
}
conn.Close()
return nil, err
}
status := strings.SplitN(line, " ", 2)
if len(status) != 2 {
conn.Close()
return nil, fmt.Errorf("invalid status : %q", line)
}
resp.Proto = status[0]
fmt.Sscanf(status[0], "HTTP/%d.%d", &resp.ProtoMajor, &resp.ProtoMinor)
resp.Status = status[1]
fmt.Sscanf(status[1], "%d", &resp.StatusCode)
break
}
m, err := tp.ReadMIMEHeader()
if err != nil {
conn.Close()
return nil, err
}
for k, v := range m {
//fmt.Printf("%s: %s\n", k, v)
if strings.ToLower(k) == "content-length" {
resp.ContentLength, err = strconv.ParseInt(v[0], 10, 64)
if err != nil {
conn.Close()
return nil, err
} else {
ofs += n
remain -= int64(n)
if remain <= 0 {
resp.Body = io.NopCloser(bytes.NewReader(buf[:ofs]))
cont = false
break
}
if time.Now().Sub(lastRequestTime).Milliseconds() >= 1000 {
conn.Close()
return nil, fmt.Errorf("time out")
}
}
}
if resp.Header.Get(k) == "" {
resp.Header.Set(k, v[0])
v = v[1:]
}
for _, vv := range v {
resp.Header.Add(k, vv)
}
}
if c.Jar != nil {
if rc := resp.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
if resp.Header.Get("Transfer-Encoding") == "chunked" {
// chunked
cur := 0
end := 0
for {
length := 0
if len(buf) < cur+6 {
// This is not a very accurate check, but in many cases it should be fine.
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", cur+6)
}
for i := 0; ; i++ {
buf[cur+i], err = br.ReadByte()
if err != nil {
conn.Close()
return nil, err
}
length = i + 1
if i > 1 && buf[cur+i-1] == '\r' && buf[cur+i] == '\n' {
break
}
}
//fmt.Printf("cur:%d length:%d\n", cur, length)
size, err := strconv.ParseInt(string(buf[cur:cur+length-2]), 16, 64)
if err != nil {
conn.Close()
return nil, err
}
//cur += length
//fmt.Printf("cur:%d length:%d size:%d\n", cur, length, size)
end = cur + int(size) + 2 // size + 2 (\r\n)
if len(buf) < end {
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", end)
}
for i := 0; i < int(size)+2; i++ {
buf[cur+i], err = br.ReadByte()
if err != nil {
conn.Close()
return nil, err
}
}
cur += int(size)
if size == 0 {
end = end - 2
break
}
}
//fmt.Printf("%q\n", buf[:end])
resp.Body = io.NopCloser(bytes.NewReader(buf[:end]))
} else {
end := int(resp.ContentLength)
if len(buf) < end {
return nil, fmt.Errorf("slice out of range : use http.SetBuf() to change the allocation to %d bytes or more", end)
}
for i := 0; i < end; i++ {
buf[i], err = br.ReadByte()
if err != nil {
conn.Close()
return nil, err
}
}
resp.Body = io.NopCloser(bytes.NewReader(buf[:end]))
}
return resp, conn.Close()
+9 -3
View File
@@ -71,10 +71,13 @@ func (d *Driver) ConnectTCPSocket(addr, port string) error {
name[6] = byte(ipaddr[2])
name[7] = byte(ipaddr[3])
_, err = d.Rpc_lwip_connect(socket, name, uint32(len(name)))
result, err := d.Rpc_lwip_connect(socket, name, uint32(len(name)))
if err != nil {
return err
}
if result == -1 {
return fmt.Errorf("failed to connect to %d.%d.%d.%d port %s", addr[0], addr[1], addr[2], addr[3], port)
}
readset := []byte{}
writeset := []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
@@ -341,8 +344,11 @@ func (d *Driver) ReadSocket(b []byte) (n int, err error) {
if err != nil {
return 0, err
}
if nn < 0 {
return 0, fmt.Errorf("error %d", n)
if nn == -76 {
// no data
return 0, nil
} else if nn < 0 {
return 0, fmt.Errorf("error %d", nn)
} else if nn == 0 || nn == -30848 {
return 0, d.DisconnectSocket()
}
-1
View File
@@ -1,5 +1,4 @@
//go:build pybadge
// +build pybadge
package shifter
-1
View File
@@ -1,5 +1,4 @@
//go:build rp2040
// +build rp2040
package ssd1289
-1
View File
@@ -1,5 +1,4 @@
//go:build stm32wlx
// +build stm32wlx
package sx126x
+11 -4
View File
@@ -19,10 +19,11 @@ type DistanceMode uint8
type RangeStatus uint8
type rangingData struct {
mm uint16
status RangeStatus
signalRateMCPS int32 //MCPS : Mega Count Per Second
ambientRateMCPS int32
mm uint16
status RangeStatus
signalRateMCPS int32 //MCPS : Mega Count Per Second
ambientRateMCPS int32
effectiveSPADCount uint16
}
type resultBuffer struct {
@@ -337,6 +338,11 @@ func (d *Device) AmbientRate() int32 {
return d.rangingData.ambientRateMCPS
}
// EffectiveSPADCount returns the effective number of SPADs
func (d *Device) EffectiveSPADCount() uint16 {
return d.rangingData.effectiveSPADCount
}
// getRangingData stores in the buffer the ranging data
func (d *Device) getRangingData() {
d.rangingData.mm = uint16((uint32(d.results.mmCrosstalkSD0)*2011 + 0x0400) / 0x0800)
@@ -384,6 +390,7 @@ func (d *Device) getRangingData() {
d.rangingData.signalRateMCPS = 1000000 * int32(d.results.signalRateCrosstalkMCPSSD0) / (1 << 7)
d.rangingData.ambientRateMCPS = 1000000 * int32(d.results.ambientRateMCPSSD0) / (1 << 7)
d.rangingData.effectiveSPADCount = d.results.effectiveSPADCount
}
// setupManualCalibration configures the manual calibration
+323
View File
@@ -0,0 +1,323 @@
package wifinina
import (
"bufio"
"bytes"
"fmt"
"io"
"strconv"
"strings"
"time"
"tinygo.org/x/drivers/net/http"
)
func (d *Device) ListenAndServe(addr string, handler http.Handler) error {
if handler == nil {
handler = http.DefaultServeMux
}
server := newServer(d, handler)
if err := server.listen(addr); err != nil {
return err
}
for {
client, err := server.accept()
if err != nil {
return err
}
if err := client.handleHTTP(); err != nil {
return err
}
if err = client.stop(); err != nil {
return err
}
}
return nil
}
// Server stuff
type server struct {
device *Device
handler http.Handler
sock uint8
clients map[uint8]*client // keyed by client sock
}
func newServer(device *Device, handler http.Handler) *server {
return &server{
device: device,
handler: handler,
sock: NoSocketAvail,
clients: make(map[uint8]*client),
}
}
func portFromAddr(addr string) (uint16, error) {
// ignore anything before ':' in address
i := strings.LastIndex(addr, ":")
if i < 0 {
return 0, fmt.Errorf("Missing ':' in address")
}
v, err := strconv.ParseUint(addr[i+1:], 10, 16)
if err != nil {
return 0, fmt.Errorf("Parsing address err: %s", err)
}
return uint16(v), nil
}
func (s *server) listen(addr string) error {
port, err := portFromAddr(addr)
if err != nil {
return fmt.Errorf("Getting port err: %s", err)
}
s.sock, err = s.device.GetSocket()
if err != nil {
return fmt.Errorf("Getting socket err: %s", err)
}
if s.sock == NoSocketAvail {
return fmt.Errorf("No socket available")
}
return s.device.StartServer(port, s.sock, ProtoModeTCP)
}
func (s *server) availServer(sock uint8) (uint8, error) {
d := s.device
d.mu.Lock()
defer d.mu.Unlock()
if err := d.waitForChipSelect(); err != nil {
d.spiChipDeselect()
return NoSocketAvail, fmt.Errorf("Wait for CS: %s", err)
}
l := d.sendCmd(CmdAvailDataTCP, 1)
l += d.sendParam8(sock, true)
d.addPadding(l)
d.spiChipDeselect()
_, err := d.waitRspCmd1(CmdAvailDataTCP)
if err != nil {
return NoSocketAvail, fmt.Errorf("Wait for Rsp: %s", err)
}
newsock, err := d.getUint16(2, err)
if err != nil {
return NoSocketAvail, fmt.Errorf("getUint16: %s", err)
}
return uint8(newsock >> 8), nil
}
func (s *server) accept() (*client, error) {
for {
sock, err := s.availServer(s.sock)
if err != nil {
return nil, fmt.Errorf("accept: %w", err)
}
if sock == NoSocketAvail {
continue
}
if client, ok := s.clients[sock]; ok {
return client, nil
}
client := newClient(s, sock)
s.clients[sock] = client
return client, nil
}
}
// client stuff
type client struct {
server *server
device *Device
sock uint8
// HTTP request
req *http.Request
reqBuf bytes.Buffer
readBuf [256]byte
// HTTP response
res bytes.Buffer
resHdr http.Header
resBuf bytes.Buffer
statusCode int
}
func newClient(server *server, sock uint8) *client {
return &client{
server: server,
device: server.device,
sock: sock,
}
}
// client implements http.ResponseWriter interface
func (c *client) Header() http.Header {
return c.resHdr
}
func (c *client) Write(b []byte) (int, error) {
return c.resBuf.Write(b)
}
func (c *client) WriteHeader(statusCode int) {
c.statusCode = statusCode
}
func (c *client) status() uint8 {
d := c.device
d.mu.Lock()
defer d.mu.Unlock()
if err := d.waitForChipSelect(); err != nil {
d.spiChipDeselect()
return 0
}
l := d.sendCmd(CmdGetClientStateTCP, 1)
l += d.sendParam8(c.sock, true)
d.addPadding(l)
d.spiChipDeselect()
_, err := d.waitRspCmd1(CmdGetClientStateTCP)
if err != nil {
return 0
}
status, err := d.getUint8(1, err)
if err != nil {
return 0
}
return status
}
func (c *client) stop() error {
if err := c.device.StopClient(c.sock); err != nil {
return err
}
// Wait max 5 secs for the connection to close
for i := 0; i < 50 && c.status() != TCPStateClosed; i++ {
time.Sleep(100 * time.Millisecond)
}
if c.status() != TCPStateClosed {
return fmt.Errorf("stop failed, client status %x", c.status())
}
return nil
}
func (c *client) handleHTTP() error {
c.reqBuf.Reset()
end := -1
// read the request
start := time.Now()
for {
// TODO use Server.ReadTimeout
if time.Since(start) > 1*time.Second {
return fmt.Errorf("ReadTimeout")
}
n, err := c.device.GetDataBuf(c.sock, c.readBuf[:])
if err != nil {
return fmt.Errorf("GetDataBuf: %s", err)
}
if n == 0 {
time.Sleep(1 * time.Millisecond)
continue
}
c.reqBuf.Write(c.readBuf[:n])
bytesSoFar := c.reqBuf.Bytes()
if end == -1 {
// search for blank line marking end-of-header
end = bytes.Index(bytesSoFar, []byte("\r\n\r\n"))
if end == -1 {
continue
}
// found end-of-header; parse header
end += len([]byte("\r\n\r\n"))
bufio := bufio.NewReader(bytes.NewReader(bytesSoFar[:end]))
c.req, err = http.ReadRequest(bufio)
if err != nil {
return err
}
}
v := c.req.Header.Get("Content-Length")
if v == "" {
// no body; we're done reading request
break
}
length, _ := strconv.Atoi(v)
if end+length == len(bytesSoFar) {
// got the whole body
body := bytes.NewReader(bytesSoFar[end:])
c.req.Body = io.NopCloser(body)
break
}
// continue reading request...
}
// build the response
c.statusCode = 200
c.resHdr = http.Header{}
c.resHdr.Add(`Content-Type`, `text/html; charset=UTF-8`)
c.resHdr.Add(`Connection`, `close`)
c.resBuf.Reset()
c.server.handler.ServeHTTP(c, c.req)
c.resHdr.Add(`Content-Length`, fmt.Sprintf("%d", c.resBuf.Len()))
c.res.Reset()
fmt.Fprintf(&c.res, "HTTP/1.1 %d %s\r\n", c.statusCode,
http.StatusText(c.statusCode))
if err := c.resHdr.Write(&c.res); err != nil {
return err
}
c.res.WriteByte(byte('\n'))
c.res.Write(c.resBuf.Bytes())
// send the response
written, err := c.device.SendData(c.res.Bytes(), c.sock)
if err != nil {
return err
}
if written == 0 {
return ErrDataNotWritten
}
if sent, _ := c.device.CheckDataSent(c.sock); !sent {
return ErrCheckDataError
}
return nil
}
-2
View File
@@ -1,5 +1,4 @@
//go:build none
// +build none
package main
@@ -285,7 +284,6 @@ func main() {
}
defer f.Close()
fmt.Fprintln(f, "//go:build", architectures[*arch].buildTag)
fmt.Fprintln(f, "// +build", architectures[*arch].buildTag)
f.WriteString(`
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build cortexm
// +build cortexm
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo.riscv32
// +build tinygo.riscv32
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build avr
// +build avr
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build cortexm
// +build cortexm
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build !baremetal
// +build !baremetal
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build tinygo.riscv32
// +build tinygo.riscv32
package ws2812
-1
View File
@@ -1,5 +1,4 @@
//go:build xtensa
// +build xtensa
package ws2812