Compare commits

..

81 Commits

Author SHA1 Message Date
sago35 3c1aaa9a9f Add error check for d.bus.Tx() 2024-07-18 08:35:57 +09:00
sago35 3f4a9d82f7 Add check for which 2024-07-16 09:00:34 +09:00
sago35 19c9fe6db3 Add error handling 2024-07-14 13:37:13 +09:00
sago35 315dbef694 dht20: add I2C driver for DHT20 temperature and humidity sensor 2024-07-13 10:48:33 +09:00
Ron Evans ee3842f639 pcf8591: add ADC only implementation for I2C ADC/DAC (#690)
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-07-01 22:06:25 +09:00
deadprogram 1bf1a11067 all: prepare release v0.28.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-06-18 11:38:02 +02:00
leongross 848f5def03 nit: increase verbosity of espat NetNotify error (#684)
espat: increase verbosity of espat NetNotify error
2024-06-14 17:36:07 +02:00
Thomas 4a0bcba87c epd2in66b: Waveshare 2.66inch E-Paper Display Module (B) for Raspberry Pi Pico (#673)
epd2in66b: add working driver

Co-authored-by: Thomas Richner <thomas.richner@oviva.com>
2024-06-10 13:16:45 +02:00
Ayke van Laethem 7d983647ad pixel: fix Image[Monochrome].Set for larger images
For bigger images, the pixel index might not fit in a int16. Therefore,
int is needed during the calculation.

While fixing this bug, I've added a few tests that verify the Image
implementation by creating images, filling them with random data, and
then checking whether they still contain the same data. This test failed
before the patch.
2024-05-25 17:09:48 +02:00
deadprogram 831982ad33 servo: add function SetAngle() to simplify API for most common use case
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-05-25 08:34:52 +02:00
deadprogram 9063f46313 uc8151: improvements to speed and also add flicker-free mode based on @antirez code example
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-05-13 22:45:37 +02:00
gmsec 2a621dc3b1 Add driver for MCP9808 i2c temperature sensor (#676)
mcp9808: add support for temperature sensor
2024-05-12 10:42:03 +02:00
deadprogram 7dbca2a543 uc8151: correct DrawBitmap() also refactor SendCommand() and SendData() for clarity
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-05-09 15:37:57 +02:00
deadprogram 50b6f18cc2 uc8151: update to support all functions needed by tinygl and board package Displayer interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-05-08 16:35:21 +02:00
sago35 bb0e6b8ba8 Fix typo and move initialization of neo to init() 2024-05-06 11:19:19 +02:00
sago35 5eeba138a4 Simplify examples/ws2812 2024-05-06 11:19:19 +02:00
deadprogram 1095629f62 ssd1306: add Sleep() function for Displayer interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-24 13:00:20 +02:00
deadprogram bf0b383176 ssd1306: add rotation functions for Displayer interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-24 13:00:20 +02:00
Elias Naur f206f6f56f ft6336: ignore bogus touch events
At least one ft6336 device reports all 255 values from the first read
after reset or poweron, even after waiting the specified 300ms reset
delay.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-04-21 12:00:03 +02:00
deadprogram a0293643b3 ssd1306: add DrawBitmap() function to complete Displayer interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-21 11:52:21 +02:00
deadprogram 60801ba852 pixel: add support for Monochrome types such as the SSD1306 display
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-13 15:50:30 +02:00
deadprogram a74770b2e6 rtl8720dn: implement ConnectModeAP
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-01 07:40:46 +02:00
deadprogram 3ed09d3fe1 wifinina: implement ConnectModeAP
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-01 07:40:46 +02:00
sago35 22581dfd58 encoders: add atsamd21, atsamd51, atsame5x 2024-02-29 15:29:41 +01:00
deadprogram 31f09d93b8 all: update for relase v0.27
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-26 19:55:23 +01:00
deadprogram 0ea969f25a docs: update LICENSE year
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-26 19:55:23 +01:00
Niccolò Maggioni 8665d44e0f Use int16 for ADXL345 readings (#656)
ADXL345: fix: use int16 for ADXL345 readings
2024-02-24 19:16:06 +01:00
deadprogram c344e5d879 ssd1306: improvements needed for Thumby SPI display
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-23 20:07:40 -05:00
BCG 308763f500 Adding driver for rotary encoder support 2024-02-15 16:55:54 +01:00
deadprogram c41f2e472d rtl8720dn, wifinina: use drivers package version as the driver version
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-27 16:43:48 +01:00
Scott Feldman aa7bd47c68 examples: add classic network snake test example
Adding this example to test multiple concurrent socket connections.
2024-01-24 08:25:20 +01:00
Scott Feldman e7931c6a22 wifinina: fix concurrency issues with multiple sockets
wifinina driver was not handling concurrent socket connections
correctly.  When trying to make multiple socket connections, the sockfd
returned by the first Socket() call would be the same sockfd returned by
subsequent Socket() calls.  The problem is the sockfd returned by
Socket() isn't used until Connect() (or Appect()).  This would result in
Connect() trying to use the same sockfd for multiple connections,
causing wifinina fw to lock up.

The solution in this PR is to create a new sockfd space managed by the
driver that gives the app a unique, safe sockfd for each connection.
The real underlying sock fd returned by fw is set on Connect() (or
Accept()), and mapped back to the apps sockfd using a map:

    sockets map[int]*Socket // keyed by sockfd

Where Socket has a reference to the fw sock:

    type Socket struct {
            protocol        int
            clientConnected bool
            laddr           netip.AddrPort // Set in Bind()
            raddr           netip.AddrPort // Set in Connect()
            sock                           // Device socket, as returned from w.getSocket()
    }
2024-01-22 13:32:57 -08:00
deadprogram 3c5e17423a netlink, examples: use 'ninafw' tag instead of individual board tags to simplify maintenence. Also see PR #4085 in the main TinyGo repo
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-17 08:47:00 +01:00
deadprogram 0262122ccd rtl8720dn: allow connecting to open wifi access points
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-12 10:45:53 +01:00
Scott Feldman 7d24c3c285 wioterminal: fix check for bad Wifi connect
rpc_wifi_connect() will return 0 on successful connection, so check for
that.  Also, check that if passphrase is given, that it's the minimum 8
chars per WPA Wifi.
2024-01-11 12:43:50 +01:00
Scott Feldman 5c0f0480bc fix wifinina UDP send
Fix an error I introduced in porting wifinina to netdev.  The driver was
starting a client on the socket once, during Connect.  The first UDP
send on the socket would succeed, any subsequent sends would fail.  The
fix is to start the client on the socket for each UDP send.

I think I see the logic in this design, so the fix makes sense.  If the
device was sending to many UDP clients, it could use a single socket,
but change the dst addr for each send.  The pkt data would be queued to
hw just once, and then sent from hw to each client dst addr.  This would
be a real efficient way to multicast to many clients.
2024-01-10 17:40:25 +01:00
Scott Feldman 8642886f73 correct netdever Accept() prototype
According to man page accept(2), accept returns new client sockfd and
remote peer ip:port.  This patch corrects the Accept() prototype in the
netdever interface to not take in an ip:port arg, but rather return an
ip:port for remote peer.

Tested with examples/net/tcpecho on wioterminal and nano-rp2040.  Here's
a run with wioterminal:

SERVER
============
sfeldma@nuc:~/work/drivers$ tinygo flash -monitor -target wioterminal -size short -stack-size=8kb ./examples/net/tcpecho
code    data     bss |   flash     ram
110876    2552   11212 |  113428   13764
Connected to /dev/ttyACM2. Press Ctrl-C to exit.

Realtek rtl8720dn Wifi network device driver (rtl8720dn)

Driver version           : 0.0.1
RTL8720 firmware version : 2.1.2
MAC address              : 2c:f7:f1:1c:9b:2f

Connecting to Wifi SSID 'test'...CONNECTED

DHCP-assigned IP         : 10.0.0.140
DHCP-assigned subnet     : 255.255.255.0
DHCP-assigned gateway    : 10.0.0.1

Starting TCP server listening on :8080
Client 10.0.0.190:50000 connected
Client 10.0.0.190:50000 closed

CLIENT
=============
nc -p 50000 10.0.0.140 8080
2023-12-19 09:33:54 +01:00
Simon Dismo 1a96fc4547 Add more line speeds to mcp2515.go (#626)
mcp2515: adding the possibility to configure lower line speeds on the CAN bus.
2023-12-11 20:40:36 +01:00
Scott Feldman 3fabdc5c96 smoketest: add stack-size param for net tests. 2023-12-06 20:09:39 +01:00
deadprogram a8928d137e modules: add natiu package for tests
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-06 20:09:39 +01:00
Scott Feldman 709fc77960 fix examples/net/socket to work with netip API 2023-12-06 20:09:39 +01:00
Scott Feldman d6ae0b0d8b store Bind laddr in netip.AddrPort 2023-12-06 20:09:39 +01:00
Scott Feldman 7a7235f83b move netdev interface to use net/netip for IP addr/ports 2023-12-06 20:09:39 +01:00
Scott Feldman 3089bf8b1b net: updates/cleanup/docs for net, netdev, and netlink 2023-12-06 20:09:39 +01:00
Scott Feldman 196d1dd58d add tcpip stack framework
Add basis for TCP/IP stack.  The stack implements Netdever interface for
the top-end, and calls into a Netlinker interface on the bottom-end.
Each TCP/IP stack instance represents a L3/L4 endpoint with an IP
address.  The Netlinker is bound when creating the stack.  E.g.:

	spi, cs, wlreg, irq := cyw43439.PicoWSpi(0)
	cyw43 := cyw43439.NewDevice(spi, cs, wlreg, irq, irq)
	stack := tcpip.NewStack(cyw43)
	netdev.UseNetdev(stack)

Here, the cyw43439 driver is the Netlinker for the stack.  The new stack
is a Netdever, so we tell the "net" package to use the stack as the
netdev.  The stack manages L3/L4 socket connections, ultimately calling
into the Netlinker to send/recv L2 Ethernet pkts.
2023-12-06 20:09:39 +01:00
Scott Feldman 1fd8a768ae netlink: add L2 bridge/bond/vlan intermediate drivers
This adds three new L2 (intermediate) drivers for bridge/bond/vlan.
Theses drivers are incomplete but illustrate how to stack L2 drivers.
Here are some examples of how these driver would stack with the cy243439
driver:

  Bridge: bridge two cyw43 devices together, connecting the two LANs:

	cyw43_0 := cyw43439.NewDevice(...)
	cyw43_1 := cyw43439.NewDevice(...)

	bridge := NewBridge([]netlink.Netlinker{cyw43_0, cyw43_1})

	stack := tcpip.NewStack(bridge)
	netdev.UseNetdev(stack)

  Bond: bond two cyw43 devices together, creating one logical device.
  The first physical device is primary, the second is backup (fail-over)
  device:

	cyw43_0 := cyw43439.NewDevice(...)  // primary
	cyw43_1 := cyw43439.NewDevice(...)  // secondary (backup)

	bond := NewBond([]netlink.Netlinker{cyw43_0, cyw43_1})

	stack := tcpip.NewStack(bond)
	netdev.UseNetdev(stack)

   Vlan: add tagged VLAN ID=100 to cyw43:

	cyw43 := cyw43439.NewDevice(...)

	vlan100 := NewVlan(100, cyw43)

	stack := tcpip.NewStack(vlan100)
	netdev.UseNetdev(stack)
2023-12-06 20:09:39 +01:00
Scott Feldman 8238f96319 move netdev and netlink into their own packages and out of drivers
This moves the netdev/netlink namespace out of drivers and into their
own packages.  Also, defines netdev and netlink as L3/L4 and L2 OSI
layers, respectively.  Move some L3 functionality from netlink to
netdev (GetIPAddr).

For netlink, add ConnectParams for NetConnect to pass in L2 connection
parameters (ssid, pass, auth_type, etc).  Also adds connection mode
(STA, AP, etc).

For netlink, add SendEth and RecvEthFunc funcs to handle L2 send/recv of
Ethernet pkts.
2023-12-06 20:09:39 +01:00
Scott Feldman e7d51d3c73 Add new MQTT client example using natiu-mqtt
Add new MQTT client example using natiu-mqtt
2023-12-06 20:09:39 +01:00
Scott Feldman 4bf631a7e3 s/ConnectTimeo/ConnectTimeout, s/WatchdogTimeo/WatchdogTimeout/ 2023-12-06 20:09:39 +01:00
Scott Feldman 3c4df6e811 wifinina: add 'unknown failure' reason code for AP connect 2023-12-06 20:09:39 +01:00
Scott Feldman 255c639ad4 wifinina: add ResetIsHigh cfg switch for MKR 1010 (copied from #561) 2023-12-06 20:09:39 +01:00
Scott Feldman 276feecc20 Add network device driver model, netdev 2023-12-06 20:09:39 +01:00
deadprogram 00b1b4fbfb smoketest: allow stack-size flag as it is needed for net examples
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-06 12:52:56 +01:00
SoftTacos 3b183ad6ed added support for SK6812 to WS2812 device (#610)
sk6812: added support for SK6812 to WS2812 device
2023-12-04 11:17:20 +01:00
Thomas Richner 68da68c8c8 seesaw: remove delay from Read(...) 2023-12-03 21:39:00 -05:00
Thomas Richner f7b80ef95a seesaw: added example and smoketest 2023-12-03 21:39:00 -05:00
Thomas Richner 933c9e127d seesaw: device support and tests 2023-12-03 21:39:00 -05:00
Ayke van Laethem 92050d90da sgp30: add the now-obsolete SGP30 air quality sensor
Tested with a rp2040.

TODO: add the ability to set the absolute humidity for more accurate
sensor details. The formula for that is rather complex, so I've left
this as a future addition.
2023-12-01 07:44:49 +01:00
Ayke van Laethem 93cbba5d8b pixel: implement RGB555 pixel format as used by the GameBoy Advance 2023-11-24 18:13:04 +01:00
Ayke van Laethem 6cf07aff4c pyportal_boing: update to use DrawBitmap
Replace DrawRGBBitmap8 with DrawBitmap, following the change in the
previous commit.

This improves performance from 86fps to 100fps! I didn't investigate
why, but I suspect it's because it now needs only a single store instead
of two to update a pixel.
2023-11-23 17:27:00 +01:00
Ayke van Laethem af33129f41 ili9341: st7735: st7789: add DrawBitmap method
This adds a new DrawBitmap method, which is meant to replace
DrawRGBBitmap8.
2023-11-23 17:27:00 +01:00
Ayke van Laethem 100aadf585 st7789: make the display generic over RGB565 and RGB444
Same as for st7735 in the previous commit.

In addition, this avoids allocating a big chunk of memory on _every_
draw operation (even SetPixel) and instead reuses it across draw
operations. This makes the driver a whole lot more efficient.
2023-11-23 17:27:00 +01:00
Ayke van Laethem 4a9667ffef st7735: make the display generic over RGB565 and RGB444
Using RGB444 instead of RGB565 can speed up graphics operations by up to
25%, especially on slow screens. But for full support, all parts of the
driver need to be aware of the color format.

It's possible to do this using a regular configuration variable, but
it's unlikely to be very efficient. Hence the usage of generics.
2023-11-23 17:27:00 +01:00
Ayke van Laethem f96a70915e pixel: add package for efficiently working with raw pixel buffers
This has been optimized for working with SPI displays like the ST7789.
By working directly in the native color format of the display, graphics
operations can be much, _much_ faster.

Also, this makes it easier to use a different color format like RGB444
simply by changing the generic type.
2023-11-23 17:27:00 +01:00
Ayke van Laethem 3e64e754a2 epd2in13: use better black/white approximation
The previoius behavior was that entirely black pixels were treated as
white, and anything else as black. That's at least counter-intuitive.
This patch changes the behavior to actually look at the color values and
use a cutoff around medium gray: darker colors are treated as black, and
lighter colors are treated as white.

This is a backwards incompatible change, but I think this behavior makes
a lot more sense.
2023-11-09 10:07:19 +01:00
Ayke van Laethem 2c2da5c7bb epd2in13: add Sleep method like other displays
For details, see: https://github.com/tinygo-org/drivers/pull/548
2023-11-07 10:39:14 +01:00
Ayke van Laethem 14994a3f31 epd2in13: unify rotation configuration with other displays
This commit updates rotation behavior to match other displays.
For more information, see: https://github.com/tinygo-org/drivers/pull/550

This changes the signature of `SetRotation` but I don't think any
existing code will be affected by this change.
2023-11-07 10:39:14 +01:00
deadprogram 47dfeb9e94 examples/lora/lorawan: modify atcmd and basic demo to support choosing
any one of the supported regions at compile time by using ldflags.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-26 08:32:04 +02:00
deadprogram f20d1759d3 examples/lora/lorawan: add missing functions for simulated interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-26 08:32:04 +02:00
deadprogram 6b79a1b386 lora/lorawan: refactor shared functionality for ChannelUS, etc into embedded type
named channel, do the same for RegionSettings, and then change RegionSettings to
just Settings to avoid the redundant naming.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-26 08:32:04 +02:00
Emilio Garcia 7dd1067cc1 LoRa WAN add setter functions 2023-10-26 08:32:04 +02:00
Emilio Garcia 4edb771c5b fix lora us915 logic to step into 500 kHz range 2023-10-26 08:32:04 +02:00
Mirac Kara e95cfe66c1 LoRa WAN US915 Support
Adds a driver for us 915 protocol to the lora WAN drivers.
2023-10-26 08:32:04 +02:00
Thomas Richner 4edb58c0c5 fix-tests: fix broken testrunner 2023-10-25 09:57:40 +02:00
Thomas Richner f384e2db48 fix-tests: migrated legacy I2C 2023-10-25 09:57:40 +02:00
sago35 7c96387845 sh1106: fix I2C interface and add smoketest 2023-10-14 11:43:06 +02:00
Christian Ege 182d4c6ebb sh1106: fixed the description of the device struct
It looks like there was an copy paste left over. This is corrected to be
concise.

Signed-off-by: Christian Ege <ch@ege.io>
2023-10-09 08:59:44 +02:00
Thomas Richner dc2de4f9ed adafruit4650: support for Adafruite 4650 feather OLED 2023-10-06 09:03:32 +02:00
Christian Ege 36a12dd7a2 at24cx: fixed the description of the device struct
It looks like there was an copy paste left over. This is corrected to be
concise.

Signed-off-by: Christian Ege <ch@ege.io>
2023-10-06 08:44:12 +02:00
Christian Ege 00992756eb ds3231: fix the description in the example
It looks like there was a copy paste leftover. This got corrected to be
concise.

Signed-off-by: Christian Ege <ch@ege.io>
2023-10-06 08:44:12 +02:00
Ayke van Laethem 715c33d4b0 all: prepare for CGo changes in TinyGo
For details, see: https://github.com/tinygo-org/tinygo/pull/3927
This change just means we need to be more careful to use the right type,
now that types like C.uint32_t don't match to the Go equivalent (like
uint32).
2023-10-05 10:01:25 +02:00
198 changed files with 10604 additions and 17037 deletions
+125
View File
@@ -1,3 +1,128 @@
0.28.0
---
- **new devices**
- **epd2in66b**
- Waveshare 2.66inch E-Paper Display Module (B) for Raspberry Pi Pico (#673)
- **mcp9808**
- Add driver for MCP9808 i2c temperature sensor (#676)
- **enhancements**
- **encoders**
- add atsamd21, atsamd51, atsame5x
- **pixel**
- add support for Monochrome types such as the SSD1306 display
- **rtl8720dn**
- implement ConnectModeAP
- **servo**
- add function SetAngle() to simplify API for most common use case
- **ssd1306**
- add DrawBitmap() function to complete Displayer interface
- add rotation functions for Displayer interface
- add Sleep() function for Displayer interface
- **uc8151**
- improvements to speed and also add flicker-free mode based on @antirez code example
- update to support all functions needed by tinygl and board package Displayer interface
- **wifinina**
- implement ConnectModeAP
- **bugfixes**
- **ft6336**
- ignore bogus touch events
- **pixel**
- fix Image[Monochrome].Set for larger images
- **uc8151**
- correct DrawBitmap() also refactor SendCommand() and SendData() for clarity
- **ws2812**
- Fix typo and move initialization of neo to init()
- **examples**
- **ws2812**
- Simplify examples/ws2812
0.27.0
---
- **core**
- prepare for CGo changes in TinyGo
- **new devices**
- **adafruit4650**
- support for Adafruit 4650 feather OLED
- **net**
- new networking support based on tinygo net package
- **pixel**
- add package for efficiently working with raw pixel buffers
- **rotary**
- Adding driver for rotary encoder support
- **seesaw**
- Adding support for Adafruit Seesaw platform
- **sgp30**
- add SGP30 air quality sensor
- **sk6812**
- added support for SK6812 to WS2812 device (#610)
- **enhancements**
- **epd2in13**
- add Sleep method like other displays
- unify rotation configuration with other displays
- use better black/white approximation
- **ili9341**
- add DrawBitmap method
- **lora/lorawan**
- LoRa WAN US915 Support
- LoRa WAN add setter functions
- refactor shared functionality for channels/regions
- **mcp2515**
- Add more line speeds to mcp2515.go (#626)
- **rtl8720dn**
- use drivers package version as the driver version
- **ssd1306**
- improvements needed for Thumby SPI display
- **st7735**
- make the display generic over RGB565 and RGB444
- **st7789**
- add DrawBitmap method
- make the display generic over RGB565 and RGB444
- **wifinina**
- add ResetIsHigh cfg switch for MKR 1010 (copied from #561)
- maintenence. Also see PR #4085 in the main TinyGo repo
- use drivers package version as the driver version
- **bugfixes**
- **adxl345**
- Use int16 for ADXL345 readings (#656)
- **at24cx**
- fixed the description of the device struct
- **rtl8720dn**
- allow connecting to open wifi access points
- fix check for bad Wifi connect
- **sh1106**
- fix I2C interface and add smoketest
- fixed the description of the device struct
- **wifinina**
- add 'unknown failure' reason code for AP connect
- fix concurrency issues with multiple sockets
- fix wifinina UDP send
- **examples**
- **ds3231**
- fix the description in the example
- **lorawan**
- add missing functions for simulated interface
- modify atcmd and basic demo to support choosing any one of the supported regions at compile time by using ldflags
- **net**
- all networking examples now using netdev and netlink.
- **build**
- **all**
- fix broken testrunner
- migrated legacy I2C
- add natiu package for tests
- **smoketest**
- add stack-size param for net tests.
- allow stack-size flag as it is needed for net examples
0.26.0
---
- **core**
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018-2023 The TinyGo Authors. All rights reserved.
Copyright (c) 2018-2024 The TinyGo Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
+1 -1
View File
@@ -19,7 +19,7 @@ rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst
# Recursively find all *_test.go files from cwd & reduce to unique dir names
HAS_TESTS = $(sort $(dir $(call rwildcard,,*_test.go)))
# Exclude anything we explicitly don't want to test for whatever reason
EXCLUDE_TESTS = image
EXCLUDE_TESTS = image waveshare-epd/epd2in66b
TESTS = $(filter-out $(addsuffix /%,$(EXCLUDE_TESTS)),$(HAS_TESTS))
unit-test:
+233
View File
@@ -0,0 +1,233 @@
### Table of Contents
- ["net" Package](#net-package)
- [Using "net" Package](#using-net-package)
- [Using "net/http" Package](#using-nethttp-package)
- [Using "crypto/tls" Package](#using-cryptotls-package)
- [Using Sockets](#using-sockets)
## "net" Package
TinyGo's "net" package is ported from Go. The port offers a subset of Go's
"net" package. The subset maintains Go 1 compatiblity guarantee. A Go
application that uses "net" will most-likey just work on TinyGo if the usage is
within the subset offered. (There may be external constraints such as limited
SRAM on some targets that may limit full "net" functionality).
Continue below for details on using "net" and "net/http" packages.
See src/net/READMD.md in the TinyGo repo for more details on maintaining
TinyGo's "net" package.
## Using "net" Package
Ideally, TinyGo's "net" package would be Go's "net" package and applications
using "net" would just work, as-is. TinyGo's net package is a partial port of
Go's net package, so some things may not work because they have not been
ported.
There are a few features excluded during the porting process, in particular:
- No IPv6 support
- No DualStack support
Run ```go doc -all ./src/net``` in TinyGo repo to see full listing of what has
been ported. Here is a list of things known to work. You can find examples
of these at [examples/net](examples/net/).
### What is Known to Work
(These are all IPv4 only).
- TCP client and server
- UDP client
- TLS client
- HTTP client and server
- HTTPS client
- NTP client (UDP)
- MQTT client (paho & natiu)
- WebSocket client and server
Multiple sockets can be opened in a single app. For example, the app could run
as an http server listen on port :80 and also use NTP to get the current time
or send something over MQTT. There is a practical limit to the number of
active sockets per app, around 8 or 10, so don't go crazy.
Applications using Go's net package will need a few setup steps to work with
TinyGo's net package. The steps are required before using "net".
### Step 1: Probe to Load Network Driver
Call Probe() to load the correct network driver for your target. Probe()
allows the app to work on multiple targets.
```go
package main
import (
"tinygo.org/x/drivers/netlink/probe"
)
func main() {
// load network driver for target
link, dev := probe.Probe()
...
}
```
Probe() will load the driver with default configuration for the target. For
custom configuration, the app can open code Probe() for the target
requirements.
Probe() returns a [Netlinker](netlink/README.md) and a
[Netdever](netdev/README.md), interfaces implemented by the network driver.
Next, we'll use the Netlinker interface to connect the target to an IP network.
### Step 2: Connect to an IP Network
Before the net package is fully functional, we need to connect the target to an
IP network.
```go
package main
import (
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
func main() {
// load network driver for target
link, _ := probe.Probe()
// Connect target to IP network
link.NetConnect(&netlink.ConnectParams{
Ssid: "my SSID",
Passphrase: "my passphrase",
})
// OK to use "net" from here on
...
}
```
Optionally, get notified of IP network connects and disconnects:
```go
link.Notify(func(e netlink.Event) {
switch e {
case netlink.EventNetUp: println("Network UP")
case netlink.EventNetDown: println("Network DOWN")
})
```
Here is an example of an http server listening on port :8080:
```go
package main
import (
"fmt"
"net/http"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
func HelloServer(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
func main() {
// load network driver for target
link, _ := probe.Probe()
// Connect target to IP network
link.NetConnect(&netlink.ConnectParams{
Ssid: "my SSID",
Passphrase: "my passphrase",
})
// Serve it up
http.HandleFunc("/", HelloServer)
http.ListenAndServe(":8080", nil)
}
```
## Using "net/http" Package
TinyGo's net/http package is a partial port of Go's net/http package, providing
a subset of the full net/http package. There are a few features excluded
during the porting process, in particular:
- No HTTP/2 support
- No TLS support for HTTP servers (no https servers)
- HTTP client request can't be reused
HTTP client methods (http.Get, http.Head, http.Post, and http.PostForm) are
functional. Dial clients support both HTTP and HTTPS URLs.
HTTP server methods and objects are mostly ported, but for HTTP only; HTTPS
servers are not supported.
HTTP request and response handling code is mostly ported, so most the intricacy
of parsing and writing headers is handled as in the full net/http package.
Run ```go doc -all ./src/net/http``` in TinyGo repo to see full listing.
## Using "crypto/tls" Package
TinyGo's TLS support (crypto/tls) relies on hardware offload of the TLS
protocol. This is different from Go's crypto/tls package which handles the TLS
protocol in software.
TinyGo's TLS support is only available for client applications. You can
http.Get() to an https:// address, but you cannot http.ListenAndServeTLS() an
https server.
The offloading hardware has pre-defined TLS certificates built-in.
## Using Sockets
The Netdever interface is a BSD socket-like interface so an application can make direct
socket calls, bypassing the "net" package for the lowest overhead.
Here is a simple TCP client application using direct sockets:
```go
package main
import (
"net" // only need to parse IP address
"tinygo.org/x/drivers/netdev"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
func main() {
// load network driver for target
link, dev := probe.Probe()
// Connect target to IP network
link.NetConnect(&netlink.ConnectParams{
Ssid: "my SSID",
Passphrase: "my passphrase",
})
// omit error handling
sock, _ := dev.Socket(netdev.AF_INET, netdev.SOCK_STREAM, netdev.IPPROTO_TCP)
dev.Connect(sock, "", net.ParseIP("10.0.0.100"), 8080)
dev.Send(sock, []bytes("hello"), 0, 0)
dev.Close(sock)
link.NetDisconnect()
}
```
+1 -1
View File
@@ -3,7 +3,7 @@
[![PkgGoDev](https://pkg.go.dev/badge/tinygo.org/x/drivers)](https://pkg.go.dev/tinygo.org/x/drivers) [![Build](https://github.com/tinygo-org/drivers/actions/workflows/build.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/drivers/actions/workflows/build.yml)
This package provides a collection of 101 different hardware drivers for devices such as sensors and displays that can be used together with [TinyGo](https://tinygo.org).
This package provides a collection of over 100 different hardware drivers for devices such as sensors, displays, wireless adaptors, and actuators, that can be used together with [TinyGo](https://tinygo.org).
For the complete list, please see:
https://tinygo.org/docs/reference/devices/
+196
View File
@@ -0,0 +1,196 @@
// Package adafruit4650 implements a driver for the Adafruit FeatherWing OLED - 128x64 OLED display.
// The display is backed itself by a SH1107 driver chip.
//
// Store: https://www.adafruit.com/product/4650
//
// Documentation: https://learn.adafruit.com/adafruit-128x64-oled-featherwing
package adafruit4650
import (
"image/color"
"time"
"tinygo.org/x/drivers"
)
const DefaultAddress = 0x3c
const (
commandSetLowColumn = 0x00
commandSetHighColumn = 0x10
commandSetPage = 0xb0
)
const (
width = 128
height = 64
)
// Device represents an Adafruit 4650 device
type Device struct {
bus drivers.I2C
Address uint8
buffer []byte
width int16
height int16
}
// New creates a new device, not configuring anything yet.
func New(bus drivers.I2C) Device {
return Device{
bus: bus,
Address: DefaultAddress,
width: width,
height: height,
}
}
// Configure initializes the display with default configuration
func (d *Device) Configure() error {
bufferSize := d.width * d.height / 8
d.buffer = make([]byte, bufferSize)
// This sequence is an amalgamation of the datasheet, official Arduino driver, CircuitPython driver and other drivers
initSequence := []byte{
0xae, // display off, sleep mode
//0xd5, 0x41, // set display clock divider (from original datasheet)
0xd5, 0x51, // set display clock divider (from Adafruit driver)
0xd9, 0x22, // pre-charge/dis-charge period mode: 2 DCLKs/2 DCLKs (POR)
0x20, // memory mode
0x81, 0x4f, // contrast setting = 0x4f
0xad, 0x8a, // set dc/dc pump
0xa0, // segment remap, flip-x
0xc0, // common output scan direction
0xdc, 0x00, // set display start line 0 (POR=0)
0xa8, 0x3f, // multiplex ratio, height - 1 = 0x3f
0xd3, 0x60, // set display offset mode = 0x60
0xdb, 0x35, // VCOM deselect level = 0.770 (POR)
0xa4, // entire display off, retain RAM, normal status (POR)
0xa6, // normal (not reversed) display
0xaf, // display on
}
err := d.writeCommands(initSequence)
if err != nil {
return err
}
// recommended in the datasheet, same in other drivers
time.Sleep(100 * time.Millisecond)
return nil
}
// ClearDisplay clears the image buffer as well as the actual display
func (d *Device) ClearDisplay() error {
d.ClearBuffer()
return d.Display()
}
// ClearBuffer clears the buffer
func (d *Device) ClearBuffer() {
bzero(d.buffer)
}
// SetPixel modifies the internal buffer. Since this display has a bit-depth of 1 bit any non-zero
// color component will be treated as 'on', otherwise 'off'.
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
if x < 0 || x >= d.width || y < 0 || y >= d.height {
return
}
// RAM layout
// *-----> y
// |
// x| col0 col1 ... col63
// v p0 a0 b0 ..
// a1 b1 ..
// .. .. ..
// a7 b7 ..
// p1 a0 b0
// a1 b1
//
//flip y - so the display orientation matches the silk screen labeling etc.
y = d.height - y - 1
page := x / 8
bytesPerPage := d.height
byteIndex := y + bytesPerPage*page
bit := x % 8
if (c.R | c.G | c.B) != 0 {
d.buffer[byteIndex] |= 1 << uint8(bit)
} else {
d.buffer[byteIndex] &^= 1 << uint8(bit)
}
}
// Display sends the whole buffer to the screen
func (d *Device) Display() error {
bytesPerPage := d.height
pages := (d.width + 7) / 8
for page := int16(0); page < pages; page++ {
err := d.setRAMPosition(uint8(page), 0)
if err != nil {
return err
}
offset := page * bytesPerPage
err = d.writeRAM(d.buffer[offset : offset+bytesPerPage])
if err != nil {
return err
}
}
return nil
}
// setRAMPosition updates the device's current page and column position
func (d *Device) setRAMPosition(page uint8, column uint8) error {
if page > 15 {
panic("page out of bounds")
}
if column > 127 {
panic("column out of bounds")
}
setPage := commandSetPage | (page & 0xF)
lo := column & 0xF
setLowColumn := commandSetLowColumn | lo
hi := (column >> 4) & 0x7
setHighColumn := commandSetHighColumn | hi
cmds := []byte{
setPage,
setLowColumn,
setHighColumn,
}
return d.writeCommands(cmds)
}
// Size returns the current size of the display.
func (d *Device) Size() (w, h int16) {
return d.width, d.height
}
func (d *Device) writeCommands(commands []byte) error {
onlyCommandsFollowing := byte(0x00)
return d.bus.Tx(uint16(d.Address), append([]byte{onlyCommandsFollowing}, commands...), nil)
}
func (d *Device) writeRAM(data []byte) error {
onlyRAMFollowing := byte(0x40)
return d.bus.Tx(uint16(d.Address), append([]byte{onlyRAMFollowing}, data...), nil)
}
func bzero(buf []byte) {
for i := range buf {
buf[i] = 0
}
}
+176
View File
@@ -0,0 +1,176 @@
package adafruit4650
import (
"bytes"
_ "embed"
"encoding/hex"
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"os"
"testing"
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freemono"
)
//go:embed expected_hello_world.png
var expectedHelloWorld []byte
// mockBus mocks a fake i2c device adafruit4650 display.
// The memory layout assumes that clients set up the device in a particular way and always send complete
// pages to the device buffer.
type mockBus struct {
img draw.Image
line int
addr uint8
currentPage int
currentColumn int
}
func (m *mockBus) Tx(addr uint16, w, r []byte) error {
if addr != uint16(m.addr) {
panic("unexpected address")
}
if r != nil {
panic("mock does not support reads")
}
if w[0] == 0x00 {
if w[1]&0xf0 == 0xb0 {
m.currentPage = int(w[1] & 0x0f)
lo := w[2] & 0x0f
hi := w[2] & 0x07
m.currentColumn = int(hi<<4 | lo)
}
return nil
}
if w[0] != 0x40 {
panic("unexpected first byte: " + hex.EncodeToString(w[0:1]))
}
return m.writeRAM(w[1:])
}
func newMock() *mockBus {
m := image.NewRGBA(image.Rect(0, 0, width, height))
return &mockBus{img: m, addr: DefaultAddress, currentPage: -1, currentColumn: -1}
}
func (m *mockBus) writeRAM(data []byte) error {
// RAM layout
// *-----> y
// |
// x| col0 col1 ... col63
// v p0 a0 b0 ..
// a1 b1 ..
// .. .. ..
// a7 b7 ..
// p1 a0 b0
// a1 b1
//
fmt.Printf("writing page %d\n", m.currentPage)
// assuming entire pages will be written
for x := 0; x < 8; x++ {
for y := 0; y < height; y++ {
col := data[y]
c := color.Black
if col&(1<<x) != 0 {
c = color.White
}
m.img.Set(x+m.currentPage*8, height-y-1, c)
}
}
return nil
}
func (m *mockBus) toImage() *image.RGBA {
container := image.NewRGBA(m.img.Bounds().Inset(-1))
draw.Draw(container, container.Bounds(), image.NewUniform(color.RGBA{G: 255, A: 255}), image.Point{}, draw.Over)
draw.Draw(container, m.img.Bounds(), m.img, image.Point{}, draw.Over)
return container
}
func TestDevice_Display(t *testing.T) {
bus := newMock()
dev := New(bus)
dev.Configure()
drawPlus(&dev)
drawHellowWorld(&dev)
//when
dev.Display()
//then
actual := bus.toImage()
expected, err := png.Decode(bytes.NewReader(expectedHelloWorld))
if err != nil {
panic(err)
}
assertEqualImages(t, actual, expected)
}
func drawPlus(d drivers.Displayer) {
for i := int16(0); i < 128; i++ {
d.SetPixel(i, 32, color.RGBA{R: 1})
}
for i := int16(0); i < 64; i++ {
d.SetPixel(64, i, color.RGBA{R: 1})
}
}
func drawHellowWorld(d drivers.Displayer) {
tinyfont.WriteLine(d, &freemono.Regular9pt7b, 0, 32, "Hello World!", color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
}
func assertEqualImages(t testing.TB, actual, expected image.Image) {
if actual.Bounds().Dx() != expected.Bounds().Dx() || actual.Bounds().Dy() != expected.Bounds().Dy() {
f := writeImage(actual)
t.Fatalf("differing size: was %v, expected %v, saved actual to %s", actual.Bounds(), expected.Bounds(), f)
}
bb := expected.Bounds()
for x := bb.Min.X; x < bb.Max.X; x++ {
for y := bb.Min.Y; y < bb.Max.Y; y++ {
actualBB := actual.Bounds()
if actual.At(x+actualBB.Min.X, y+actualBB.Min.Y) != expected.At(x, y) {
f := writeImage(actual)
t.Fatalf("different pixel at %d/%d: %v != %v, saved actual at %s", x, y, actual.At(x, y), expected.At(x, y), f)
}
}
}
}
func writeImage(img image.Image) string {
fn := fmt.Sprintf("%d.png", time.Now().Unix())
f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
panic(err)
}
defer f.Close()
err = png.Encode(f, img)
if err != nil {
panic(err)
}
return fn
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

+7 -7
View File
@@ -95,16 +95,16 @@ func (d *Device) Restart() {
func (d *Device) ReadAcceleration() (x int32, y int32, z int32, err error) {
rx, ry, rz := d.ReadRawAcceleration()
x = d.dataFormat.convertToIS(rx)
y = d.dataFormat.convertToIS(ry)
z = d.dataFormat.convertToIS(rz)
x = int32(d.dataFormat.convertToIS(rx))
y = int32(d.dataFormat.convertToIS(ry))
z = int32(d.dataFormat.convertToIS(rz))
return
}
// ReadRawAcceleration reads the sensor values and returns the raw x, y and z axis
// from the adxl345.
func (d *Device) ReadRawAcceleration() (x int32, y int32, z int32) {
func (d *Device) ReadRawAcceleration() (x int16, y int16, z int16) {
data := []byte{0, 0, 0, 0, 0, 0}
legacy.ReadRegister(d.bus, uint8(d.Address), REG_DATAX0, data)
@@ -140,7 +140,7 @@ func (d *Device) SetRange(sensorRange Range) bool {
}
// convertToIS adjusts the raw values from the adxl345 with the range configuration
func (d *dataFormat) convertToIS(rawValue int32) int32 {
func (d *dataFormat) convertToIS(rawValue int16) int16 {
switch d.sensorRange {
case RANGE_2G:
return rawValue * 4 // rawValue * 2 * 1000 / 512
@@ -190,6 +190,6 @@ func (b *bwRate) toByte() (bits uint8) {
}
// readInt converts two bytes to int16
func readIntLE(msb byte, lsb byte) int32 {
return int32(uint16(msb) | uint16(lsb)<<8)
func readIntLE(msb byte, lsb byte) int16 {
return int16(uint16(msb) | uint16(lsb)<<8)
}
+145 -224
View File
@@ -8,16 +8,15 @@ import (
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
)
// Device wraps an I2C connection to a APDS-9960 device.
type Device struct {
bus drivers.I2C
_txerr error
gesture gestureData
buf [8]byte
Address uint8
mode uint8
gesture gestureData
}
// Configuration for APDS-9960 device.
@@ -47,24 +46,15 @@ type gestureData struct {
received bool
}
// for enabling various device functions.
type encfg uint8
// data := []byte{gen<<6 | pien<<5 | aien<<4 | wen<<3 | pen<<2 | aen<<1 | pon}
const (
enPON encfg = 1 << iota
enAEN
enPEN
enWEN
enAIEN
enPIEN
enGEN
)
func (e encfg) write7bits(b []byte) {
for i := uint8(0); i < 7; i++ {
b[i] = byte(e>>(6-i)) & 1
}
// for enabling various device function
type enableConfig struct {
GEN bool
PIEN bool
AIEN bool
WEN bool
PEN bool
AEN bool
PON bool
}
// New creates a new APDS-9960 connection. The I2C bus must already be
@@ -78,8 +68,9 @@ func New(bus drivers.I2C) Device {
// Connected returns whether APDS-9960 has been found.
// It does a "who am I" request and checks the response.
func (d *Device) Connected() bool {
d.txNew()
return d.txRead8(APDS9960_ID_REG) == 0xAB && d.txErr() == nil
data := []byte{0}
legacy.ReadRegister(d.bus, d.Address, APDS9960_ID_REG, data)
return data[0] == 0xAB
}
// GetMode returns current engine mode
@@ -88,82 +79,65 @@ func (d *Device) GetMode() uint8 {
}
// DisableAll turns off the device and all functions
func (d *Device) DisableAll() error {
err := d.enable(0)
if err != nil {
return err
}
d.txWrite8(APDS9960_GCONF4_REG, 0)
err = d.txErr()
if err == nil {
d.mode = MODE_NONE
d.gesture.detected = GESTURE_NONE
}
return err
func (d *Device) DisableAll() {
d.enable(enableConfig{})
legacy.WriteRegister(d.bus, d.Address, APDS9960_GCONF4_REG, []byte{0x00})
d.mode = MODE_NONE
d.gesture.detected = GESTURE_NONE
}
// SetProximityPulse sets proximity pulse length (4, 8, 16, 32) and count (1..64)
// SetProximityPulse sets proximity pulse length (4, 8, 16, 32) and count (1~64)
// default: 16, 64
func (d *Device) SetProximityPulse(length, count uint8) error {
d.txNew()
d.txWrite8(APDS9960_PPULSE_REG, getPulseLength(length)<<6|getPulseCount(count))
return d.txErr()
func (d *Device) SetProximityPulse(length, count uint8) {
legacy.WriteRegister(d.bus, d.Address, APDS9960_PPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)})
}
// SetGesturePulse sets gesture pulse length (4, 8, 16, 32) and count (1..64)
// SetGesturePulse sets gesture pulse length (4, 8, 16, 32) and count (1~64)
// default: 16, 64
func (d *Device) SetGesturePulse(length, count uint8) error {
d.txNew()
d.txWrite8(APDS9960_GPULSE_REG, getPulseLength(length)<<6|getPulseCount(count))
return d.txErr()
func (d *Device) SetGesturePulse(length, count uint8) {
legacy.WriteRegister(d.bus, d.Address, APDS9960_GPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)})
}
// SetADCIntegrationCycles sets ALS/color ADC internal integration cycles (1..256, 1 cycle = 2.78 ms)
// default: 4 (approx. 10 ms)
func (d *Device) SetADCIntegrationCycles(cycles uint16) error {
// SetADCIntegrationCycles sets ALS/color ADC internal integration cycles (1~256, 1 cycle = 2.78 ms)
// default: 4 (~10 ms)
func (d *Device) SetADCIntegrationCycles(cycles uint16) {
if cycles > 256 {
cycles = 256
}
d.txNew()
d.txWrite8(APDS9960_ATIME_REG, uint8(256-cycles))
return d.txErr()
legacy.WriteRegister(d.bus, d.Address, APDS9960_ATIME_REG, []byte{uint8(256 - cycles)})
}
// SetGains sets proximity/gesture gain (1, 2, 4, 8x) and ALS/color gain (1, 4, 16, 64x)
// default: 1, 1, 4
func (d *Device) SetGains(proximityGain, gestureGain, colorGain uint8) error {
d.txNew()
d.txWrite8(APDS9960_CONTROL_REG, getProximityGain(proximityGain)<<2|getALSGain(colorGain))
d.txWrite8(APDS9960_GCONF2_REG, getProximityGain(gestureGain)<<5)
return d.txErr()
func (d *Device) SetGains(proximityGain, gestureGain, colorGain uint8) {
legacy.WriteRegister(d.bus, d.Address, APDS9960_CONTROL_REG, []byte{getProximityGain(proximityGain)<<2 | getALSGain(colorGain)})
legacy.WriteRegister(d.bus, d.Address, APDS9960_GCONF2_REG, []byte{getProximityGain(gestureGain) << 5})
}
// LEDBoost sets proximity and gesture LED current level (100, 150, 200, 300 (%))
// default: 100
func (d *Device) LEDBoost(percent uint16) error {
func (d *Device) LEDBoost(percent uint16) {
var v uint8
switch {
case percent < 125:
switch percent {
case 100:
v = 0
case percent < 175:
case 150:
v = 1
case percent < 250:
case 200:
v = 2
default:
v = 3 // Maximum case.
case 300:
v = 3
}
d.txNew()
d.txWrite8(APDS9960_CONFIG2_REG, 0x01|(v<<4))
return d.txErr()
legacy.WriteRegister(d.bus, d.Address, APDS9960_CONFIG2_REG, []byte{0x01 | v<<4})
}
// Setthreshold sets threshold (0..255) for detecting gestures
// Setthreshold sets threshold (0~255) for detecting gestures
// default: 30
func (d *Device) Setthreshold(t uint8) {
d.gesture.threshold = t
}
// Setsensitivity sets sensivity (0..100) for detecting gestures
// Setsensitivity sets sensivity (0~100) for detecting gestures
// default: 20
func (d *Device) Setsensitivity(s uint8) {
if s > 100 {
@@ -173,69 +147,47 @@ func (d *Device) Setsensitivity(s uint8) {
}
// EnableProximity starts the proximity engine
func (d *Device) EnableProximity() error {
func (d *Device) EnableProximity() {
if d.mode != MODE_NONE {
err := d.DisableAll()
if err != nil {
return err
}
d.DisableAll()
}
err := d.enable(enPON | enPEN | enWEN)
if err == nil {
d.mode = MODE_PROXIMITY
}
return err
}
// Err returns the current error state of the device if encountered during I2C communication.
// After a call to Err the error is cleared.
func (d *Device) Err() error {
err := d.txErr()
d.txNew()
return err
d.enable(enableConfig{PON: true, PEN: true, WEN: true})
d.mode = MODE_PROXIMITY
}
// ProximityAvailable reports if proximity data is available
func (d *Device) ProximityAvailable() bool {
if d.mode != MODE_PROXIMITY {
return false
if d.mode == MODE_PROXIMITY && d.readStatus("PVALID") {
return true
}
status, err := d.ReadStatus()
return err == nil && status.PVALID()
return false
}
// ReadProximity reads proximity data (0..255)
// ReadProximity reads proximity data (0~255)
func (d *Device) ReadProximity() (proximity int32) {
if d.mode != MODE_PROXIMITY {
return 0
}
d.txNew()
val := d.txRead8(APDS9960_PDATA_REG)
return 255 - int32(val)
data := []byte{0}
legacy.ReadRegister(d.bus, d.Address, APDS9960_PDATA_REG, data)
return 255 - int32(data[0])
}
// EnableColor starts the color engine
func (d *Device) EnableColor() (err error) {
func (d *Device) EnableColor() {
if d.mode != MODE_NONE {
err = d.DisableAll()
if err != nil {
return err
}
d.DisableAll()
}
err = d.enable(enPON | enAEN | enWEN)
if err == nil {
d.mode = MODE_COLOR
}
return err
d.enable(enableConfig{PON: true, AEN: true, WEN: true})
d.mode = MODE_COLOR
}
// ColorAvailable reports if color data is available
func (d *Device) ColorAvailable() bool {
if d.mode != MODE_COLOR {
return false
if d.mode == MODE_COLOR && d.readStatus("AVALID") {
return true
}
status, err := d.ReadStatus()
return err == nil && status.AVALID()
return false
}
// ReadColor reads color data (red, green, blue, clear color/brightness)
@@ -243,36 +195,28 @@ func (d *Device) ReadColor() (r int32, g int32, b int32, clear int32) {
if d.mode != MODE_COLOR {
return
}
d.txNew()
data := d.buf[:8]
const numLowRegs = APDS9960_GDATAH_REG - APDS9960_CDATAL_REG + 1
for i := uint8(0); i < numLowRegs; i++ {
data[i] = d.txRead8(i + APDS9960_CDATAL_REG)
}
data[numLowRegs] = d.txRead8(APDS9960_BDATAL_REG)
data[numLowRegs+1] = d.txRead8(APDS9960_BDATAH_REG)
if d.txErr() != nil {
return
}
data := []byte{0, 0, 0, 0, 0, 0, 0, 0}
legacy.ReadRegister(d.bus, d.Address, APDS9960_CDATAL_REG, data[:1])
legacy.ReadRegister(d.bus, d.Address, APDS9960_CDATAH_REG, data[1:2])
legacy.ReadRegister(d.bus, d.Address, APDS9960_RDATAL_REG, data[2:3])
legacy.ReadRegister(d.bus, d.Address, APDS9960_RDATAH_REG, data[3:4])
legacy.ReadRegister(d.bus, d.Address, APDS9960_GDATAL_REG, data[4:5])
legacy.ReadRegister(d.bus, d.Address, APDS9960_GDATAH_REG, data[5:6])
legacy.ReadRegister(d.bus, d.Address, APDS9960_BDATAL_REG, data[6:7])
legacy.ReadRegister(d.bus, d.Address, APDS9960_BDATAH_REG, data[7:])
clear = int32(uint16(data[1])<<8 | uint16(data[0]))
r = int32(uint16(data[3])<<8 | uint16(data[2]))
g = int32(uint16(data[5])<<8 | uint16(data[4]))
b = int32(uint16(data[7])<<8 | uint16(data[6]))
return r, g, b, clear
return
}
// EnableGesture starts the gesture engine
func (d *Device) EnableGesture() error {
func (d *Device) EnableGesture() {
if d.mode != MODE_NONE {
err := d.DisableAll()
if err != nil {
return err
}
}
err := d.enable(enPON | enPEN | enGEN | enWEN)
if err != nil {
return err
d.DisableAll()
}
d.enable(enableConfig{PON: true, PEN: true, GEN: true, WEN: true})
d.mode = MODE_GESTURE
d.gesture.detected = GESTURE_NONE
d.gesture.gXDelta = 0
@@ -280,7 +224,6 @@ func (d *Device) EnableGesture() error {
d.gesture.gXPrevDelta = 0
d.gesture.gYPrevDelta = 0
d.gesture.received = false
return nil
}
// GestureAvailable reports if gesture data is available
@@ -288,26 +231,29 @@ func (d *Device) GestureAvailable() bool {
if d.mode != MODE_GESTURE {
return false
}
d.txNew()
gstatus := d.txRead8(APDS9960_GSTATUS_REG)
if gstatus&1 == 0 {
data := []byte{0, 0, 0, 0}
// check GVALID
legacy.ReadRegister(d.bus, d.Address, APDS9960_GSTATUS_REG, data[:1])
if data[0]&0x01 == 0 {
return false
}
availableDataSets := d.txRead8(APDS9960_GFLVL_REG)
// get number of data sets available in FIFO
legacy.ReadRegister(d.bus, d.Address, APDS9960_GFLVL_REG, data[:1])
availableDataSets := data[0]
if availableDataSets == 0 {
return false
}
data := d.buf[:]
// read up, down, left and right proximity data from FIFO
var dataSets [32][4]uint8
const numAddrs = APDS9960_GFIFO_R_REG - APDS9960_GFIFO_U_REG + 1
for i := uint8(0); i < availableDataSets; i++ {
for j := uint8(0); j < numAddrs; j++ {
data[j] = d.txRead8(j + APDS9960_GFIFO_U_REG)
}
if d.txErr() != nil {
return false
}
legacy.ReadRegister(d.bus, d.Address, APDS9960_GFIFO_U_REG, data[:1])
legacy.ReadRegister(d.bus, d.Address, APDS9960_GFIFO_D_REG, data[1:2])
legacy.ReadRegister(d.bus, d.Address, APDS9960_GFIFO_L_REG, data[2:3])
legacy.ReadRegister(d.bus, d.Address, APDS9960_GFIFO_R_REG, data[3:4])
for j := uint8(0); j < 4; j++ {
dataSets[i][j] = data[j]
}
@@ -369,11 +315,9 @@ func (d *Device) ReadGesture() (gesture int32) {
// private functions
func (d *Device) configureDevice(cfg Configuration) error {
err := d.DisableAll() // turn off everything
if err != nil {
return err
}
func (d *Device) configureDevice(cfg Configuration) {
d.DisableAll() // turn off everything
// "default" settings
if cfg.ProximityPulseLength == 0 {
cfg.ProximityPulseLength = 16
@@ -406,92 +350,69 @@ func (d *Device) configureDevice(cfg Configuration) error {
d.gesture.sensitivity = 20
}
err = d.SetProximityPulse(cfg.ProximityPulseLength, cfg.ProximityPulseCount)
if err != nil {
return err
d.SetProximityPulse(cfg.ProximityPulseLength, cfg.ProximityPulseCount)
d.SetGesturePulse(cfg.GesturePulseLength, cfg.GesturePulseCount)
d.SetGains(cfg.ProximityGain, cfg.GestureGain, cfg.ColorGain)
d.SetADCIntegrationCycles(cfg.ADCIntegrationCycles)
if cfg.LEDBoost > 0 {
d.LEDBoost(cfg.LEDBoost)
}
err = d.SetGesturePulse(cfg.GesturePulseLength, cfg.GesturePulseCount)
if err != nil {
return err
}
err = d.SetGains(cfg.ProximityGain, cfg.GestureGain, cfg.ColorGain)
if err != nil {
return err
}
err = d.SetADCIntegrationCycles(cfg.ADCIntegrationCycles)
if err == nil && cfg.LEDBoost > 0 {
err = d.LEDBoost(cfg.LEDBoost)
}
return err
}
func (d *Device) enable(cfg encfg) error {
d.txNew()
cfg.write7bits(d.buf[:7])
d.txWrite(APDS9960_ENABLE_REG, d.buf[:7])
err := d.txErr()
if err == nil && cfg&enPON != 0 {
func (d *Device) enable(cfg enableConfig) {
var gen, pien, aien, wen, pen, aen, pon uint8
if cfg.GEN {
gen = 1
}
if cfg.PIEN {
pien = 1
}
if cfg.AIEN {
aien = 1
}
if cfg.WEN {
wen = 1
}
if cfg.PEN {
pen = 1
}
if cfg.AEN {
aen = 1
}
if cfg.PON {
pon = 1
}
data := []byte{gen<<6 | pien<<5 | aien<<4 | wen<<3 | pen<<2 | aen<<1 | pon}
legacy.WriteRegister(d.bus, d.Address, APDS9960_ENABLE_REG, data)
if cfg.PON {
time.Sleep(time.Millisecond * 10)
}
return err
}
func (d *Device) txErr() error { return d._txerr }
func (d *Device) readStatus(param string) bool {
data := []byte{0}
legacy.ReadRegister(d.bus, d.Address, APDS9960_STATUS_REG, data)
func (d *Device) txNew() { d._txerr = nil }
func (d *Device) txRead8(addr uint8) uint8 {
if d._txerr != nil {
return 0
switch param {
case "CPSAT":
return data[0]>>7&0x01 == 1
case "PGSAT":
return data[0]>>6&0x01 == 1
case "PINT":
return data[0]>>5&0x01 == 1
case "AINT":
return data[0]>>4&0x01 == 1
case "PVALID":
return data[0]>>1&0x01 == 1
case "AVALID":
return data[0]&0x01 == 1
default:
return false
}
d.buf[0] = addr
d._txerr = d.bus.Tx(uint16(d.Address), d.buf[:1], d.buf[1:2])
return d.buf[1]
}
func (d *Device) txWrite8(addr uint8, val uint8) {
if d._txerr != nil {
return
}
d.buf[0] = addr
d.buf[1] = val
d._txerr = d.bus.Tx(uint16(d.Address), d.buf[:2], nil)
}
func (d *Device) txWrite(addr uint8, data []byte) {
if d._txerr != nil {
return
} else if len(data) > len(d.buf)-1 {
panic("txWrite: data too long")
}
d.buf[0] = addr
copy(d.buf[1:], data)
d._txerr = d.bus.Tx(uint16(d.Address), d.buf[:len(data)+1], nil)
}
type status uint8
const (
statusAVALID status = 1 << iota
statusPVALID
_
_
statusAINT
statusPINT
statusPGSAT
statusCPSAT
)
func (s status) CPSAT() bool { return s&statusCPSAT != 0 }
func (s status) PGSAT() bool { return s&statusPGSAT != 0 }
func (s status) PINT() bool { return s&statusPINT != 0 }
func (s status) AINT() bool { return s&statusAINT != 0 }
func (s status) PVALID() bool { return s&statusPVALID != 0 }
func (s status) AVALID() bool { return s&statusAVALID != 0 }
func (d *Device) ReadStatus() (status, error) {
d.txNew()
return status(d.txRead8(APDS9960_STATUS_REG)), d.txErr()
}
func getPulseLength(l uint8) uint8 {
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"tinygo.org/x/drivers"
)
// Device wraps an I2C connection to a DS3231 device.
// Device wraps an I2C connection to an AT24CX device.
type Device struct {
bus drivers.I2C
Address uint16
+1 -1
View File
@@ -49,7 +49,7 @@ func Sleep(duration time.Duration) {
// * The CPU frequency is lower than 256MHz. If it is higher, long sleep
// times (1-16ms) may not work correctly.
cycles := uint32(duration) * (machine.CPUFrequency() / 1000_000) / 1000
slept := C.tinygo_drivers_sleep(cycles)
slept := C.tinygo_drivers_sleep(C.uint32_t(cycles))
if !slept {
// Fallback for platforms without inline assembly support.
time.Sleep(duration)
+144
View File
@@ -0,0 +1,144 @@
// Package dht20 implements a driver for the DHT20 temperature and humidity sensor.
//
// Datasheet: https://cdn-shop.adafruit.com/product-files/5183/5193_DHT20.pdf
package dht20
import (
"errors"
"time"
"tinygo.org/x/drivers"
)
var (
errUpdateCalledTooSoon = errors.New("Update() called within 80ms is invalid")
)
// Device wraps an I2C connection to a DHT20 device.
type Device struct {
bus drivers.I2C
Address uint16
data [8]uint8
temperature float32
humidity float32
prevAccessTime time.Time
}
// New creates a new DHT20 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus drivers.I2C) Device {
return Device{
bus: bus,
Address: defaultAddress, // Using the address defined in registers.go
}
}
// Configure sets up the device for communication and initializes the registers if needed.
func (d *Device) Configure() error {
// Get the status word
d.data[0] = 0x71
err := d.bus.Tx(d.Address, d.data[:1], d.data[:1])
if err != nil {
return err
}
if d.data[0] != 0x18 {
// Initialize registers
err := d.initRegisters()
if err != nil {
return err
}
}
// Set the previous access time to the current time
d.prevAccessTime = time.Now()
return nil
}
// initRegisters initializes the registers 0x1B, 0x1C, and 0x1E to 0x00.
func (d *Device) initRegisters() error {
// Initialize register 0x1B
d.data[0] = 0x1B
d.data[1] = 0x00
err := d.bus.Tx(d.Address, d.data[:2], nil)
if err != nil {
return err
}
// Initialize register 0x1C
d.data[0] = 0x1C
d.data[1] = 0x00
err = d.bus.Tx(d.Address, d.data[:2], nil)
if err != nil {
return err
}
// Initialize register 0x1E
d.data[0] = 0x1E
d.data[1] = 0x00
err = d.bus.Tx(d.Address, d.data[:2], nil)
if err != nil {
return err
}
return nil
}
// Update reads data from the sensor and updates the temperature and humidity values.
// Note that the values obtained by this function are from the previous call to Update.
// If you want to use the most recent values, shorten the interval at which Update is called.
func (d *Device) Update(which drivers.Measurement) error {
if which&drivers.Temperature == 0 && which&drivers.Humidity == 0 {
return nil
}
// Check if 80ms have passed since the last access
if time.Since(d.prevAccessTime) < 80*time.Millisecond {
return errUpdateCalledTooSoon
}
// Check the status word Bit[7]
d.data[0] = 0x71
err := d.bus.Tx(d.Address, d.data[:1], d.data[:1])
if err != nil {
return err
}
if (d.data[0] & 0x80) == 0 {
// Read 7 bytes of data from the sensor
err := d.bus.Tx(d.Address, nil, d.data[:7])
if err != nil {
return err
}
rawHumidity := uint32(d.data[1])<<12 | uint32(d.data[2])<<4 | uint32(d.data[3])>>4
rawTemperature := uint32(d.data[3]&0x0F)<<16 | uint32(d.data[4])<<8 | uint32(d.data[5])
// Convert raw values to human-readable values
d.humidity = float32(rawHumidity) / 1048576.0 * 100
d.temperature = float32(rawTemperature)/1048576.0*200 - 50
// Trigger the next measurement
d.data[0] = 0xAC
d.data[1] = 0x33
d.data[2] = 0x00
err = d.bus.Tx(d.Address, d.data[:3], nil)
if err != nil {
return err
}
// Update the previous access time to the current time
d.prevAccessTime = time.Now()
}
return nil
}
// Temperature returns the last measured temperature.
func (d *Device) Temperature() float32 {
return d.temperature
}
// Humidity returns the last measured humidity.
func (d *Device) Humidity() float32 {
return d.humidity
}
+6
View File
@@ -0,0 +1,6 @@
package dht20
// Constants/addresses used for I2C.
// The I2C address which this device listens to.
const defaultAddress = 0x38
+34
View File
@@ -0,0 +1,34 @@
package encoders
type QuadratureDevice struct {
cfg QuadratureConfig
impl quadratureImpl
}
type QuadratureConfig struct {
Precision int
}
type quadratureImpl interface {
configure(cfg QuadratureConfig) error
readValue() int
writeValue(int)
}
func (enc *QuadratureDevice) Configure(cfg QuadratureConfig) error {
if cfg.Precision < 1 {
cfg.Precision = 4
}
enc.cfg = cfg
return enc.impl.configure(cfg)
}
// Position returns the stored int value for the encoder
func (enc *QuadratureDevice) Position() int {
return enc.impl.readValue() / enc.cfg.Precision
}
// SetPosition overwrites the currently stored value with the specified int value
func (enc *QuadratureDevice) SetPosition(v int) {
enc.impl.writeValue(v * enc.cfg.Precision)
}
+69
View File
@@ -0,0 +1,69 @@
//go:build tinygo && (rp2040 || stm32 || k210 || esp32c3 || nrf || sam || (avr && (atmega328p || atmega328pb)))
// Implementation based on:
// https://gist.github.com/aykevl/3fc1683ed77bb0a9c07559dfe857304a
// Note: build constraints in this file list targets that define machine.PinToggle.
// If this is supported for additional targets in the future, they can be added above.
package encoders
import (
"machine"
"runtime/volatile"
)
var (
states = []int8{0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}
)
// NewQuadratureViaInterrupt returns a rotary encoder device that uses GPIO
// interrupts and a lookup table to keep track of quadrature state changes.
//
// This constructur is only available for TinyGo targets for which machine.PinToggle
// is defined as a valid interrupt type.
func NewQuadratureViaInterrupt(pinA, pinB machine.Pin) *QuadratureDevice {
return &QuadratureDevice{impl: &quadInterruptImpl{pinA: pinA, pinB: pinB, oldAB: 0b00000011}}
}
type quadInterruptImpl struct {
pinA machine.Pin
pinB machine.Pin
// precision int
oldAB int
value volatile.Register32
}
func (enc *quadInterruptImpl) configure(cfg QuadratureConfig) error {
enc.pinA.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
enc.pinA.SetInterrupt(machine.PinToggle, enc.interrupt)
enc.pinB.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
enc.pinB.SetInterrupt(machine.PinToggle, enc.interrupt)
return nil
}
func (enc *quadInterruptImpl) interrupt(pin machine.Pin) {
aHigh, bHigh := enc.pinA.Get(), enc.pinB.Get()
enc.oldAB <<= 2
if aHigh {
enc.oldAB |= 1 << 1
}
if bHigh {
enc.oldAB |= 1
}
enc.writeValue(enc.readValue() + int(states[enc.oldAB&0x0f]))
}
// readValue gets the value using volatile operations and returns it as an int
func (enc *quadInterruptImpl) readValue() int {
return int(enc.value.Get())
}
// writeValue set the value to the specified int using volatile operations
func (enc *quadInterruptImpl) writeValue(v int) {
enc.value.Set(uint32(v))
}
-20
View File
@@ -1,20 +0,0 @@
package espat
import (
"time"
"tinygo.org/x/drivers/net"
)
func (d *Device) ConnectToAccessPoint(ssid, pass string, timeout time.Duration) error {
if len(ssid) == 0 {
return net.ErrWiFiMissingSSID
}
d.SetWifiMode(WifiModeClient)
return d.ConnectToAP(ssid, pass, int(timeout.Seconds()))
}
func (d *Device) Disconnect() error {
return d.DisconnectFromAP()
}
+296 -34
View File
@@ -15,41 +15,302 @@
//
// AT command set:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
// 02/2023 sfeldma@gmail.com Heavily modified to use netdev interface
package espat // import "tinygo.org/x/drivers/espat"
import (
"errors"
"fmt"
"machine"
"net"
"net/netip"
"strconv"
"strings"
"sync"
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/netdev"
"tinygo.org/x/drivers/netlink"
)
// Device wraps UART connection to the ESP8266/ESP32.
type Device struct {
bus drivers.UART
type Config struct {
// UART config
Uart *machine.UART
Tx machine.Pin
Rx machine.Pin
}
type socket struct {
inUse bool
protocol int
laddr netip.AddrPort
}
type Device struct {
cfg *Config
uart *machine.UART
// command responses that come back from the ESP8266/ESP32
response []byte
// data received from a TCP/UDP connection forwarded by the ESP8266/ESP32
socketdata []byte
data []byte
socket socket
mu sync.Mutex
}
// ActiveDevice is the currently configured Device in use. There can only be one.
var ActiveDevice *Device
// New returns a new espat driver. Pass in a fully configured UART bus.
func New(b drivers.UART) *Device {
return &Device{bus: b, response: make([]byte, 512), socketdata: make([]byte, 0, 1024)}
func NewDevice(cfg *Config) *Device {
return &Device{
cfg: cfg,
response: make([]byte, 1500),
data: make([]byte, 0, 1500),
}
}
// Configure sets up the device for communication.
func (d Device) Configure() {
ActiveDevice = &d
net.ActiveDevice = ActiveDevice
func (d *Device) NetConnect(params *netlink.ConnectParams) error {
if len(params.Ssid) == 0 {
return netlink.ErrMissingSSID
}
d.uart = d.cfg.Uart
d.uart.Configure(machine.UARTConfig{TX: d.cfg.Tx, RX: d.cfg.Rx})
// Connect to ESP8266/ESP32
fmt.Printf("Connecting to device...")
for i := 0; i < 5; i++ {
if d.Connected() {
break
}
time.Sleep(1 * time.Second)
}
if !d.Connected() {
fmt.Printf("FAILED\r\n")
return netlink.ErrConnectFailed
}
fmt.Printf("CONNECTED\r\n")
// Connect to Wifi AP
fmt.Printf("Connecting to Wifi SSID '%s'...", params.Ssid)
d.SetWifiMode(WifiModeClient)
err := d.ConnectToAP(params.Ssid, params.Passphrase, 10 /* secs */)
if err != nil {
fmt.Printf("FAILED\r\n")
return err
}
fmt.Printf("CONNECTED\r\n")
ip, err := d.Addr()
if err != nil {
return err
}
fmt.Printf("DHCP-assigned IP: %s\r\n", ip)
fmt.Printf("\r\n")
return nil
}
func (d *Device) NetDisconnect() {
d.DisconnectFromAP()
fmt.Printf("\r\nDisconnected from Wifi\r\n\r\n")
}
func (d *Device) NetNotify(cb func(netlink.Event)) {
fmt.Printf("\r\n%s\r\n", netlink.ErrNotSupported)
}
func (d *Device) GetHostByName(name string) (netip.Addr, error) {
ip, err := d.GetDNS(name)
if err != nil {
return netip.Addr{}, err
}
return netip.ParseAddr(ip)
}
func (d *Device) GetHardwareAddr() (net.HardwareAddr, error) {
return net.HardwareAddr{}, netlink.ErrNotSupported
}
func (d *Device) Addr() (netip.Addr, error) {
resp, err := d.GetClientIP()
if err != nil {
return netip.Addr{}, err
}
prefix := "+CIPSTA:ip:"
for _, line := range strings.Split(resp, "\n") {
if ok := strings.HasPrefix(line, prefix); ok {
ip := line[len(prefix)+1 : len(line)-2]
return netip.ParseAddr(ip)
}
}
return netip.Addr{}, fmt.Errorf("Error getting IP address")
}
func (d *Device) Socket(domain int, stype int, protocol int) (int, error) {
switch domain {
case netdev.AF_INET:
default:
return -1, netdev.ErrFamilyNotSupported
}
switch {
case protocol == netdev.IPPROTO_TCP && stype == netdev.SOCK_STREAM:
case protocol == netdev.IPPROTO_TLS && stype == netdev.SOCK_STREAM:
case protocol == netdev.IPPROTO_UDP && stype == netdev.SOCK_DGRAM:
default:
return -1, netdev.ErrProtocolNotSupported
}
// Only supporting single connection mode, so only one socket at a time
if d.socket.inUse {
return -1, netdev.ErrNoMoreSockets
}
d.socket.inUse = true
d.socket.protocol = protocol
return 0, nil
}
func (d *Device) Bind(sockfd int, ip netip.AddrPort) error {
d.socket.laddr = ip
return nil
}
func (d *Device) Connect(sockfd int, host string, ip netip.AddrPort) error {
var err error
var addr = ip.Addr().String()
var rport = strconv.Itoa(int(ip.Port()))
var lport = strconv.Itoa(int(d.socket.laddr.Port()))
switch d.socket.protocol {
case netdev.IPPROTO_TCP:
err = d.ConnectTCPSocket(addr, rport)
case netdev.IPPROTO_UDP:
err = d.ConnectUDPSocket(addr, rport, lport)
case netdev.IPPROTO_TLS:
err = d.ConnectSSLSocket(host, rport)
}
if err != nil {
if host == "" {
return fmt.Errorf("Connect to %s timed out", ip)
} else {
return fmt.Errorf("Connect to %s:%d timed out", host, ip.Port())
}
}
return nil
}
func (d *Device) Listen(sockfd int, backlog int) error {
switch d.socket.protocol {
case netdev.IPPROTO_UDP:
default:
return netdev.ErrProtocolNotSupported
}
return nil
}
func (d *Device) Accept(sockfd int) (int, netip.AddrPort, error) {
return -1, netip.AddrPort{}, netdev.ErrNotSupported
}
func (d *Device) sendChunk(sockfd int, buf []byte, deadline time.Time) (int, error) {
// Check if we've timed out
if !deadline.IsZero() {
if time.Now().After(deadline) {
return -1, netdev.ErrTimeout
}
}
err := d.StartSocketSend(len(buf))
if err != nil {
return -1, err
}
n, err := d.Write(buf)
if err != nil {
return -1, err
}
_, err = d.Response(1000)
if err != nil {
return -1, err
}
return n, err
}
func (d *Device) Send(sockfd int, buf []byte, flags int, deadline time.Time) (int, error) {
d.mu.Lock()
defer d.mu.Unlock()
// Break large bufs into chunks so we don't overrun the hw queue
chunkSize := 1436
for i := 0; i < len(buf); i += chunkSize {
end := i + chunkSize
if end > len(buf) {
end = len(buf)
}
_, err := d.sendChunk(sockfd, buf[i:end], deadline)
if err != nil {
return -1, err
}
}
return len(buf), nil
}
func (d *Device) Recv(sockfd int, buf []byte, flags int, deadline time.Time) (int, error) {
d.mu.Lock()
defer d.mu.Unlock()
var length = len(buf)
// Limit length read size to chunk large read requests
if length > 1436 {
length = 1436
}
for {
// Check if we've timed out
if !deadline.IsZero() {
if time.Now().After(deadline) {
return -1, netdev.ErrTimeout
}
}
n, err := d.ReadSocket(buf[:length])
if err != nil {
return -1, err
}
if n == 0 {
d.mu.Unlock()
time.Sleep(100 * time.Millisecond)
d.mu.Lock()
continue
}
return n, nil
}
}
func (d *Device) Close(sockfd int) error {
d.mu.Lock()
defer d.mu.Unlock()
d.socket.inUse = false
return d.DisconnectSocket()
}
func (d *Device) SetSockOpt(sockfd int, level int, opt int, value interface{}) error {
return netdev.ErrNotSupported
}
// Connected checks if there is communication with the ESP8266/ESP32.
@@ -57,7 +318,7 @@ func (d *Device) Connected() bool {
d.Execute(Test)
// handle response here, should include "OK"
_, err := d.Response(100)
_, err := d.Response(1000)
if err != nil {
return false
}
@@ -66,12 +327,12 @@ func (d *Device) Connected() bool {
// Write raw bytes to the UART.
func (d *Device) Write(b []byte) (n int, err error) {
return d.bus.Write(b)
return d.uart.Write(b)
}
// Read raw bytes from the UART.
func (d *Device) Read(b []byte) (n int, err error) {
return d.bus.Read(b)
return d.uart.Read(b)
}
// how long in milliseconds to pause after sending AT commands
@@ -100,9 +361,10 @@ func (d Device) Set(cmd, params string) error {
// Version returns the ESP8266/ESP32 firmware version info.
func (d Device) Version() []byte {
d.Execute(Version)
r, err := d.Response(100)
r, err := d.Response(2000)
if err != nil {
return []byte("unknown")
//return []byte("unknown")
return []byte(err.Error())
}
return r
}
@@ -132,16 +394,16 @@ func (d *Device) ReadSocket(b []byte) (n int, err error) {
d.Response(300)
count := len(b)
if len(b) >= len(d.socketdata) {
if len(b) >= len(d.data) {
// copy it all, then clear socket data
count = len(d.socketdata)
copy(b, d.socketdata[:count])
d.socketdata = d.socketdata[:0]
count = len(d.data)
copy(b, d.data[:count])
d.data = d.data[:0]
} else {
// copy all we can, then keep the remaining socket data around
copy(b, d.socketdata[:count])
copy(d.socketdata, d.socketdata[count:])
d.socketdata = d.socketdata[:len(d.socketdata)-count]
copy(b, d.data[:count])
copy(d.data, d.data[count:])
d.data = d.data[:len(d.data)-count]
}
return count, nil
@@ -157,11 +419,11 @@ func (d *Device) Response(timeout int) ([]byte, error) {
retries := timeout / pause
for {
size = d.bus.Buffered()
size = d.uart.Buffered()
if size > 0 {
end += size
d.bus.Read(d.response[start:end])
d.uart.Read(d.response[start:end])
// if "+IPD" then read socket data
if strings.Contains(string(d.response[:end]), "+IPD") {
@@ -204,18 +466,18 @@ func (d *Device) parseIPD(end int) error {
val := string(d.response[s+5 : e])
// TODO: verify count
_, err := strconv.Atoi(val)
v, err := strconv.Atoi(val)
if err != nil {
// not expected data here. what to do?
return err
}
// load up the socket data
d.socketdata = append(d.socketdata, d.response[e+1:end]...)
d.data = append(d.data, d.response[e+1:e+1+v]...)
return nil
}
// IsSocketDataAvailable returns of there is socket data available
func (d *Device) IsSocketDataAvailable() bool {
return len(d.socketdata) > 0 || d.bus.Buffered() > 0
return len(d.data) > 0 || d.uart.Buffered() > 0
}
+1 -1
View File
@@ -51,7 +51,7 @@ func (d *Device) ConnectTCPSocket(addr, port string) error {
// ConnectUDPSocket creates a new UDP connection for the ESP8266/ESP32.
func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
protocol := "UDP"
val := "\"" + protocol + "\",\"" + addr + "\"," + sendport + "," + listenport + ",2"
val := "\"" + protocol + "\",\"" + addr + "\"," + sendport + "," + listenport + ",0"
err := d.Set(TCPConnect, val)
if err != nil {
return err
+1 -4
View File
@@ -44,10 +44,7 @@ func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
d.Set(ConnectAP, val)
_, err := d.Response(ws * 1000)
if err != nil {
return err
}
return nil
return err
}
// DisconnectFromAP disconnects the ESP8266/ESP32 from the current access point.
+42
View File
@@ -0,0 +1,42 @@
package main
import (
"image/color"
"machine"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/adafruit4650"
"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freemono"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
dev := adafruit4650.New(machine.I2C0)
err := dev.Configure()
if err != nil {
panic(err)
}
drawPlus(&dev)
drawHelloWorld(&dev)
err = dev.Display()
if err != nil {
panic(err)
}
}
func drawPlus(d drivers.Displayer) {
for i := int16(0); i < 128; i++ {
d.SetPixel(i, 32, color.RGBA{R: 1})
}
for i := int16(0); i < 64; i++ {
d.SetPixel(64, i, color.RGBA{R: 1})
}
}
func drawHelloWorld(d drivers.Displayer) {
tinyfont.WriteLine(d, &freemono.Regular9pt7b, 0, 32, "Hello World!", color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
}
+13 -22
View File
@@ -8,42 +8,33 @@ import (
)
func main() {
// Sleep to catch any errors through the serial monitor.
time.Sleep(1000 * time.Millisecond)
bus := machine.I2C0
// use Nano 33 BLE Sense's internal I2C bus
err := bus.Configure(machine.I2CConfig{
SCL: machine.GP1,
SDA: machine.GP0,
Frequency: 400 * machine.KHz,
})
if err != nil {
panic(err.Error())
}
sensor := apds9960.New(bus)
// use Nano 33 BLE Sense's internal I2C bus
machine.I2C1.Configure(machine.I2CConfig{
SCL: machine.SCL1_PIN,
SDA: machine.SDA1_PIN,
Frequency: machine.TWI_FREQ_400KHZ,
})
sensor := apds9960.New(machine.I2C1)
// use default settings
sensor.Configure(apds9960.Configuration{})
if !sensor.Connected() {
println("APDS-9960 not connected!")
println("err:", sensor.Err())
return
}
println("APDS connected!")
err = sensor.EnableProximity() // enable proximity engine
if err != nil {
panic(err.Error())
}
sensor.EnableProximity() // enable proximity engine
for {
if sensor.ProximityAvailable() {
p := sensor.ReadProximity()
println("Proximity:", p)
}
if err := sensor.Err(); err != nil {
println(err.Error())
}
time.Sleep(time.Millisecond * 100)
}
}
+36
View File
@@ -0,0 +1,36 @@
package main
import (
"machine"
"strconv"
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/dht20"
)
var (
i2c = machine.I2C0
)
func main() {
i2c.Configure(machine.I2CConfig{})
sensor := dht20.New(i2c)
sensor.Configure()
// Trigger the first measurement
sensor.Update(drivers.AllMeasurements)
for {
time.Sleep(1 * time.Second)
// Update sensor dasta
sensor.Update(drivers.AllMeasurements)
temp := sensor.Temperature()
hum := sensor.Humidity()
// Note: The sensor values are from the previous measurement (1 second ago)
println("Temperature:", strconv.FormatFloat(float64(temp), 'f', 2, 64), "°C")
println("Humidity:", strconv.FormatFloat(float64(hum), 'f', 2, 64), "%")
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
// Connects to an MAG3110 I2C magnetometer.
// Connects to an DS3231 I2C Real Time Clock (RTC).
package main
import (
@@ -0,0 +1,28 @@
//go:build macropad_rp2040
package main
import (
"machine"
"tinygo.org/x/drivers/encoders"
)
var (
enc = encoders.NewQuadratureViaInterrupt(machine.ROT_A, machine.ROT_B)
)
func main() {
enc.Configure(encoders.QuadratureConfig{
Precision: 4,
})
for oldValue := 0; ; {
if newValue := enc.Position(); newValue != oldValue {
println("value: ", newValue)
oldValue = newValue
}
}
}
-145
View File
@@ -1,145 +0,0 @@
// This is a console to a ESP8266/ESP32 running on the device UART1.
// Allows you to type AT commands from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
//
// More information on the Espressif AT command set at:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
)
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
var (
// access point info
ssid string
pass string
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
console = machine.Serial
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
println("Type an AT command then press enter:")
prompt()
input := make([]byte, 64)
i := 0
for {
if console.Buffered() > 0 {
data, _ := console.ReadByte()
switch data {
case 13:
// return key
console.Write([]byte("\r\n"))
// send command to ESP8266
input[i] = byte('\r')
input[i+1] = byte('\n')
adaptor.Write(input[:i+2])
// display response
r, _ := adaptor.Response(500)
console.Write(r)
// prompt
prompt()
i = 0
continue
default:
// just echo the character
console.WriteByte(data)
input[i] = data
i++
}
}
time.Sleep(10 * time.Millisecond)
}
}
func prompt() {
print("ESPAT>")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// provide access point
func provideAP() {
println("Starting wifi network as access point '" + ssid + "'...")
adaptor.SetWifiMode(espat.WifiModeAP)
adaptor.SetAPConfig(ssid, pass, 7, espat.WifiAPSecurityWPA2_PSK)
println("Ready.")
ip, _ := adaptor.GetAPIP()
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-131
View File
@@ -1,131 +0,0 @@
// This is a sensor hub that uses a ESP8266/ESP32 running on the device UART1.
// It creates a UDP "server" you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
var (
// access point info
ssid string
pass string
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266
adaptor = espat.New(uart)
adaptor.Configure()
readyled := machine.LED
readyled.Configure(machine.PinConfig{Mode: machine.PinOutput})
readyled.High()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
// now make UDP connection
laddr := &net.UDPAddr{Port: 2222}
println("Loading UDP listener...")
conn, _ := net.ListenUDP("UDP", laddr)
println("Waiting for data...")
data := make([]byte, 50)
blink := true
for {
n, _ := conn.Read(data)
if n > 0 {
println(string(data[:n]))
conn.Write([]byte("hello back\r\n"))
}
blink = !blink
if blink {
readyled.High()
} else {
readyled.Low()
}
time.Sleep(500 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting UDP...")
conn.Close()
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// provide access point
func provideAP() {
println("Starting wifi network as access point '" + ssid + "'...")
adaptor.SetWifiMode(espat.WifiModeAP)
adaptor.SetAPConfig(ssid, pass, 7, espat.WifiAPSecurityWPA2_PSK)
println("Ready.")
ip, _ := adaptor.GetAPIP()
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-110
View File
@@ -1,110 +0,0 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates a UDP connection you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
var (
// access point info
ssid string
pass string
)
// IP address of the listener aka "hub". Replace with your own info.
const hubIP = "0.0.0.0"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
// now make UDP connection
ip := net.ParseIP(hubIP)
raddr := &net.UDPAddr{IP: ip, Port: 2222}
laddr := &net.UDPAddr{Port: 2222}
println("Dialing UDP connection...")
conn, _ := net.DialUDP("udp", laddr, raddr)
for {
// send data
println("Sending data...")
conn.Write([]byte("hello\r\n"))
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting UDP...")
conn.Close()
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-144
View File
@@ -1,144 +0,0 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
package main
import (
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net/mqtt"
)
var (
// access point info
ssid string
pass string
)
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
console = machine.Serial
adaptor *espat.Device
topic = "tinygo"
)
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl := mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
for {
println("Publishing MQTT message...")
data := []byte("{\"e\":[{ \"n\":\"hello\", \"v\":101 }]}")
token := cl.Publish(topic, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-165
View File
@@ -1,165 +0,0 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net/mqtt"
)
var (
// access point info
ssid string
pass string
)
// IP address of the MQTT broker to use. Replace with your own info.
//const server = "tcp://test.mosquitto.org:1883"
const server = "ssl://test.mosquitto.org:8883"
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are defaults for the Arduino Nano33 IoT.
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
console = machine.Serial
adaptor *espat.Device
cl mqtt.Client
topicTx = "tinygo/tx"
topicRx = "tinygo/rx"
)
func subHandler(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("[%s] ", msg.Topic())
fmt.Printf("%s\r\n", msg.Payload())
}
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl = mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
// subscribe
token := cl.Subscribe(topicRx, 0, subHandler)
token.Wait()
if token.Error() != nil {
failMessage(token.Error().Error())
}
go publishing()
select {}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
func publishing() {
for {
println("Publishing MQTT message...")
data := []byte("{\"e\":[{ \"n\":\"hello\", \"v\":101 }]}")
token := cl.Publish(topicTx, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(1000 * time.Millisecond)
}
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-113
View File
@@ -1,113 +0,0 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates a UDP connection you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
const serverIP = "0.0.0.0"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
// now make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
println("Dialing TCP connection...")
conn, err := net.DialTCP("tcp", laddr, raddr)
if err != nil {
failMessage(err.Error())
}
for {
// send data
println("Sending data...")
conn.Write([]byte("hello\r\n"))
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
if err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second); err != nil {
failMessage(err.Error())
}
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+23 -22
View File
@@ -8,15 +8,16 @@ import (
"tinygo.org/x/drivers/examples/ili9341/initdisplay"
"tinygo.org/x/drivers/examples/ili9341/pyportal_boing/graphics"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/pixel"
)
const (
BGCOLOR = 0xAD75
GRIDCOLOR = 0xA815
BGSHADOW = 0x5285
GRIDSHADOW = 0x600C
RED = 0xF800
WHITE = 0xFFFF
BGCOLOR = pixel.RGB565BE(0x75AD)
GRIDCOLOR = pixel.RGB565BE(0x15A8)
BGSHADOW = pixel.RGB565BE(0x8552)
GRIDSHADOW = pixel.RGB565BE(0x0C60)
RED = pixel.RGB565BE(0x00F8)
WHITE = pixel.RGB565BE(0xFFFF)
YBOTTOM = 123 // Ball Y coord at bottom
YBOUNCE = -3.5 // Upward velocity on ball bounce
@@ -25,7 +26,7 @@ const (
)
var (
frameBuffer = [(graphics.BALLHEIGHT + 8) * (graphics.BALLWIDTH + 8) * 2]uint8{}
frameBuffer = pixel.NewImage[pixel.RGB565BE](graphics.BALLWIDTH+8, graphics.BALLHEIGHT+8)
startTime int64
frame int64
@@ -41,7 +42,7 @@ var (
balloldy float32
// Color table for ball rotation effect
palette [16]uint16
palette [16]pixel.RGB565BE
)
var (
@@ -108,6 +109,7 @@ func main() {
width = maxx - minx + 1
height = maxy - miny + 1
buffer := frameBuffer.Rescale(int(width), int(height))
// Ball animation frame # is incremented opposite the ball's X velocity
ballframe -= ballvx * 0.5
@@ -128,7 +130,7 @@ func main() {
}
// Only the changed rectangle is drawn into the 'renderbuf' array...
var c uint16 //, *destPtr;
var c pixel.RGB565BE //, *destPtr;
bx := minx - int16(ballx) // X relative to ball bitmap (can be negative)
by := miny - int16(bally) // Y relative to ball bitmap (can be negative)
bgx := minx // X relative to background bitmap (>= 0)
@@ -149,19 +151,20 @@ func main() {
(by >= 0) && (by < graphics.BALLHEIGHT) { // inside the ball bitmap area?
// Yes, do ball compositing math...
p = graphics.Ball[int(by*(graphics.BALLWIDTH/2))+int(bx1/2)] // Get packed value (2 pixels)
var nibble uint8
if (bx1 & 1) != 0 {
c = uint16(p & 0xF)
nibble = p & 0xF
} else {
c = uint16(p >> 4)
nibble = p >> 4
} // Unpack high or low nybble
if c == 0 { // Outside ball - just draw grid
if nibble == 0 { // Outside ball - just draw grid
if graphics.Background[bgidx]&(0x80>>(bgx1&7)) != 0 {
c = GRIDCOLOR
} else {
c = BGCOLOR
}
} else if c > 1 { // In ball area...
c = palette[c]
} else if nibble > 1 { // In ball area...
c = palette[nibble]
} else { // In shadow area...
if graphics.Background[bgidx]&(0x80>>(bgx1&7)) != 0 {
c = GRIDSHADOW
@@ -176,8 +179,7 @@ func main() {
c = BGCOLOR
}
}
frameBuffer[(y*int(width)+x)*2] = byte(c >> 8)
frameBuffer[(y*int(width)+x)*2+1] = byte(c)
buffer.Set(x, y, c)
bx1++ // Increment bitmap position counters (X axis)
bgx1++
}
@@ -188,7 +190,7 @@ func main() {
bgy++
}
display.DrawRGBBitmap8(minx, miny, frameBuffer[:width*height*2], width, height)
display.DrawBitmap(minx, miny, buffer)
// Show approximate frame rate
frame++
@@ -205,6 +207,7 @@ func DrawBackground() {
w, h := display.Size()
byteWidth := (w + 7) / 8 // Bitmap scanline pad = whole byte
var b uint8
buffer := frameBuffer.Rescale(int(w), 1)
for j := int16(0); j < h; j++ {
for k := int16(0); k < w; k++ {
if k&7 > 0 {
@@ -213,13 +216,11 @@ func DrawBackground() {
b = graphics.Background[j*byteWidth+k/8]
}
if b&0x80 == 0 {
frameBuffer[2*k] = byte(BGCOLOR >> 8)
frameBuffer[2*k+1] = byte(BGCOLOR & 0xFF)
buffer.Set(int(k), 0, BGCOLOR)
} else {
frameBuffer[2*k] = byte(GRIDCOLOR >> 8)
frameBuffer[2*k+1] = byte(GRIDCOLOR & 0xFF)
buffer.Set(int(k), 0, GRIDCOLOR)
}
}
display.DrawRGBBitmap8(0, j, frameBuffer[0:w*2], w, 1)
display.DrawBitmap(0, j, buffer)
}
}
+4 -4
View File
@@ -23,20 +23,20 @@ Builds/flashes atcmd console application with simulator instead of actual LoRa r
tinygo flash -target pico ./examples/lora/lorawan/atcmd/
```
## PyBadge with LoRa Featherwing
## PyBadge with LoRa Featherwing for EU868 region
Builds/flashes atcmd console application on PyBadge using LoRa Featherwing (RFM95/SX1276).
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/atcmd/
tinygo flash -target pybadge -tags featherwing -ldflags="-X main.reg=EU868" ./examples/lora/lorawan/atcmd/
```
## LoRa-E5
## LoRa-E5 for US915 region
Builds/flashes atcmd console application on Lora-E5 using onboard SX126x.
```
tinygo flash -target lorae5 ./examples/lora/lorawan/atcmd/
tinygo flash -target lorae5 -ldflags="-X main.reg=US915" ./examples/lora/lorawan/atcmd/
```
## Joining a Public Lorawan Network
+12 -1
View File
@@ -32,6 +32,8 @@ var (
defaultTimeout uint32 = 1000
)
var reg string
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
@@ -45,7 +47,16 @@ func main() {
otaa = &lorawan.Otaa{}
lorawan.UseRadio(radio)
lorawan.UseRegionSettings(region.EU868())
switch reg {
case "AU915":
lorawan.UseRegionSettings(region.AU915())
case "EU868":
lorawan.UseRegionSettings(region.EU868())
case "US915":
lorawan.UseRegionSettings(region.US915())
default:
lorawan.UseRegionSettings(region.EU868())
}
for {
if uart.Buffered() > 0 {
+4 -4
View File
@@ -21,16 +21,16 @@ loraConnect: Connected !
tinygo flash -target pico ./examples/lora/lorawan/basic-demo
```
## PyBadge with LoRa Featherwing
## PyBadge with LoRa Featherwing for EU868 region
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/basic-demo
tinygo flash -target pybadge -tags featherwing -ldflags="-X main.reg=EU868" ./examples/lora/lorawan/basic-demo
```
## LoRa-E5
## LoRa-E5 for US915 region
```
tinygo flash -target lorae5 ./examples/lora/lorawan/basic-demo
tinygo flash -target lorae5 -ldflags="-X main.reg=US915" ./examples/lora/lorawan/basic-demo
```
+14 -3
View File
@@ -12,7 +12,10 @@ import (
"tinygo.org/x/drivers/lora/lorawan/region"
)
var debug string
var (
reg string
debug string
)
const (
LORAWAN_JOIN_TIMEOUT_SEC = 180
@@ -67,8 +70,16 @@ func main() {
// Connect the lorawan with the Lora Radio device.
lorawan.UseRadio(radio)
lorawan.UseRegionSettings(region.EU868())
switch reg {
case "AU915":
lorawan.UseRegionSettings(region.AU915())
case "EU868":
lorawan.UseRegionSettings(region.EU868())
case "US915":
lorawan.UseRegionSettings(region.US915())
default:
lorawan.UseRegionSettings(region.EU868())
}
// Configure AppEUI, DevEUI, APPKey, and public/private Lorawan Network
setLorawanKeys()
+12 -7
View File
@@ -23,13 +23,18 @@ func (sr *SimLoraRadio) Rx(timeoutMs uint32) ([]uint8, error) {
return nil, nil
}
func (sr *SimLoraRadio) SetFrequency(freq uint32) {}
func (sr *SimLoraRadio) SetIqMode(mode uint8) {}
func (sr *SimLoraRadio) SetCodingRate(cr uint8) {}
func (sr *SimLoraRadio) SetBandwidth(bw uint8) {}
func (sr *SimLoraRadio) SetCrc(enable bool) {}
func (sr *SimLoraRadio) SetSpreadingFactor(sf uint8) {}
func (sr *SimLoraRadio) LoraConfig(cnf lora.Config) {}
func (sr *SimLoraRadio) SetFrequency(freq uint32) {}
func (sr *SimLoraRadio) SetIqMode(mode uint8) {}
func (sr *SimLoraRadio) SetCodingRate(cr uint8) {}
func (sr *SimLoraRadio) SetBandwidth(bw uint8) {}
func (sr *SimLoraRadio) SetCrc(enable bool) {}
func (sr *SimLoraRadio) SetSpreadingFactor(sf uint8) {}
func (sr *SimLoraRadio) SetHeaderType(headerType uint8) {}
func (sr *SimLoraRadio) SetPreambleLength(pLen uint16) {}
func (sr *SimLoraRadio) SetPublicNetwork(enabled bool) {}
func (sr *SimLoraRadio) SetSyncWord(syncWord uint16) {}
func (sr *SimLoraRadio) SetTxPower(txPower int8) {}
func (sr *SimLoraRadio) LoraConfig(cnf lora.Config) {}
func FirmwareVersion() string {
return "simulator " + CurrentVersion()
+48
View File
@@ -0,0 +1,48 @@
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/mcp9808"
)
func main() {
//tinygo monitor
time.Sleep(time.Millisecond * 5000)
//Configure I2C (in this case, I2C0 on RPI Pico), and wire the module accordingly
machine.I2C0.Configure(machine.I2CConfig{
SCL: machine.GP1,
SDA: machine.GP0,
})
//Create sensor
sensor := mcp9808.New(machine.I2C0)
if !sensor.Connected() {
println("MCP9808 not found")
return
} else {
println("MCP9808 found")
}
time.Sleep(time.Millisecond * 1000)
//Set resolution
sensor.SetResolution(mcp9808.Maximum)
time.Sleep(time.Millisecond * 1000)
//Read temp.
temp, err := sensor.ReadTemperature()
if err != nil {
println("MCP9808 error reading temperature")
println(err.Error())
return
} else {
fmt.Printf("Temperature: %.2f \n", temp)
}
return
}
+88
View File
@@ -0,0 +1,88 @@
// This example gets an URL using http.Get(). URL scheme can be http or https.
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//
// Some targets (Arduino Nano33 IoT) don't have enough SRAM to run http.Get().
// Use the following for those targets:
//
// examples/net/webclient (for HTTP)
// examples/net/tlsclient (for HTTPS)
//go:build ninafw || wioterminal
package main
import (
"fmt"
"io"
"log"
"machine"
"net/http"
"net/url"
"strings"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
)
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
name := "John Doe"
occupation := "gardener"
params := "name=" + url.QueryEscape(name) + "&" +
"occupation=" + url.QueryEscape(occupation)
path := fmt.Sprintf("https://httpbin.org/get?%s", params)
cnt := 0
for {
fmt.Printf("Getting %s\r\n\r\n", path)
resp, err := http.Get(path)
if err != nil {
fmt.Printf("%s\r\n", err.Error())
time.Sleep(10 * time.Second)
continue
}
fmt.Printf("%s %s\r\n", resp.Proto, resp.Status)
for k, v := range resp.Header {
fmt.Printf("%s: %s\r\n", k, strings.Join(v, " "))
}
fmt.Printf("\r\n")
body, err := io.ReadAll(resp.Body)
println(string(body))
resp.Body.Close()
cnt++
fmt.Printf("-------- %d --------\r\n", cnt)
time.Sleep(10 * time.Second)
}
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+68
View File
@@ -0,0 +1,68 @@
// This example gets an URL using http.Head(). URL scheme can be http or https.
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//
// Some targets (Arduino Nano33 IoT) don't have enough SRAM to run http.Head().
// Use the following for those targets:
//
// examples/net/webclient (for HTTP)
// examples/net/tlsclient (for HTTPS)
//go:build ninafw || wioterminal
package main
import (
"bytes"
"fmt"
"log"
"machine"
"net/http"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
url string = "https://httpbin.org"
)
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
resp, err := http.Head(url)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var buf bytes.Buffer
if err := resp.Write(&buf); err != nil {
log.Fatal(err)
}
fmt.Println(string(buf.Bytes()))
link.NetDisconnect()
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+72
View File
@@ -0,0 +1,72 @@
// This example posts an URL using http.Post(). URL scheme can be http or https.
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//
// Some targets (Arduino Nano33 IoT) don't have enough SRAM to run http.Post().
// Use the following for those targets:
//
// examples/net/webclient (for HTTP)
// examples/net/tlsclient (for HTTPS)
//go:build ninafw || wioterminal
package main
import (
"bytes"
"fmt"
"io"
"log"
"machine"
"net/http"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
)
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
path := "https://httpbin.org/post"
data := []byte("{\"name\":\"John Doe\",\"occupation\":\"gardener\"}")
resp, err := http.Post(path, "application/json", bytes.NewBuffer(data))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
link.NetDisconnect()
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+73
View File
@@ -0,0 +1,73 @@
// This example posts an URL using http.PostForm(). URL scheme can be http or https.
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//
// Some targets (Arduino Nano33 IoT) don't have enough SRAM to run
// http.PostForm(). Use the following for those targets:
//
// examples/net/webclient (for HTTP)
// examples/net/tlsclient (for HTTPS)
//go:build ninafw || wioterminal
package main
import (
"fmt"
"io"
"log"
"machine"
"net/http"
"net/url"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
)
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
path := "https://httpbin.org/post"
data := url.Values{
"name": {"John Doe"},
"occupation": {"gardener"},
}
resp, err := http.PostForm(path, data)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+146
View File
@@ -0,0 +1,146 @@
// This example is an MQTT client built with the natiu-mqtt package. It sends
// machine.CPUFrequency() readings to the broker every second for 10 seconds.
//
// Note: It may be necessary to increase the stack size when using
// paho.mqtt.golang. Use the -stack-size=4KB command line option.
//go:build ninafw || wioterminal || challenger_rp2040
package main
import (
"context"
"errors"
"fmt"
"io"
"log"
"machine"
"math/rand"
"net"
"time"
mqtt "github.com/soypat/natiu-mqtt"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
broker string = "test.mosquitto.org:1883"
topic string = "cpu/freq"
)
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
clientId := "tinygo-client-" + randomString(10)
fmt.Printf("ClientId: %s\n", clientId)
// Get a transport for MQTT packets
fmt.Printf("Connecting to MQTT broker at %s\n", broker)
conn, err := net.Dial("tcp", broker)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// Create new client
client := mqtt.NewClient(mqtt.ClientConfig{
Decoder: mqtt.DecoderNoAlloc{make([]byte, 1500)},
OnPub: func(_ mqtt.Header, _ mqtt.VariablesPublish, r io.Reader) error {
message, _ := io.ReadAll(r)
fmt.Printf("Message %s received on topic %s\n", string(message), topic)
return nil
},
})
// Connect client
var varconn mqtt.VariablesConnect
varconn.SetDefaultMQTT([]byte(clientId))
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
err = client.Connect(ctx, conn, &varconn)
if err != nil {
log.Fatal("failed to connect: ", err)
}
// Subscribe to topic
ctx, _ = context.WithTimeout(context.Background(), 10*time.Second)
err = client.Subscribe(ctx, mqtt.VariablesSubscribe{
PacketIdentifier: 23,
TopicFilters: []mqtt.SubscribeRequest{
{TopicFilter: []byte(topic), QoS: mqtt.QoS0},
},
})
if err != nil {
log.Fatal("failed to subscribe to", topic, err)
}
fmt.Printf("Subscribed to topic %s\n", topic)
// Publish on topic
pubFlags, _ := mqtt.NewPublishFlags(mqtt.QoS0, false, false)
pubVar := mqtt.VariablesPublish{
TopicName: []byte(topic),
}
for i := 0; i < 10; i++ {
if !client.IsConnected() {
log.Fatal("client disconnected: ", client.Err())
}
freq := float32(machine.CPUFrequency()) / 1000000
payload := fmt.Sprintf("%.02fMhz", freq)
pubVar.PacketIdentifier++
err = client.PublishPayload(pubFlags, pubVar, []byte(payload))
if err != nil {
log.Fatal("error transmitting message: ", err)
}
time.Sleep(time.Second)
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
err = client.HandleNext()
if err != nil {
log.Fatal("handle next: ", err)
}
}
client.Disconnect(errors.New("disconnected gracefully"))
for {
select {}
}
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+114
View File
@@ -0,0 +1,114 @@
// This example is an MQTT client built with the paho-mqtt package. It sends
// machine.CPUFrequency() readings to the broker every second for 10 seconds.
//
// Note: It may be necessary to increase the stack size when using
// paho.mqtt.golang. Use the -stack-size=4KB command line option.
//go:build ninafw || wioterminal || challenger_rp2040
package main
import (
"fmt"
"log"
"machine"
"math/rand"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
broker string = "tcp://test.mosquitto.org:1883"
)
var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("Message %s received on topic %s\n", msg.Payload(), msg.Topic())
}
var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {
fmt.Println("Connected")
}
var connectionLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
fmt.Printf("Connection Lost: %s\n", err.Error())
}
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
clientId := "tinygo-client-" + randomString(10)
fmt.Printf("ClientId: %s\n", clientId)
options := mqtt.NewClientOptions()
options.AddBroker(broker)
options.SetClientID(clientId)
options.SetDefaultPublishHandler(messagePubHandler)
options.OnConnect = connectHandler
options.OnConnectionLost = connectionLostHandler
fmt.Printf("Connecting to MQTT broker at %s\n", broker)
client := mqtt.NewClient(options)
token := client.Connect()
if token.Wait() && token.Error() != nil {
panic(token.Error())
}
topic := "cpu/freq"
token = client.Subscribe(topic, 1, nil)
if token.Wait() && token.Error() != nil {
panic(token.Error())
}
fmt.Printf("Subscribed to topic %s\n", topic)
for i := 0; i < 10; i++ {
freq := float32(machine.CPUFrequency()) / 1000000
payload := fmt.Sprintf("%.02fMhz", freq)
token = client.Publish(topic, 0, false, payload)
if token.Wait() && token.Error() != nil {
panic(token.Error())
}
time.Sleep(time.Second)
}
client.Disconnect(100)
for {
select {}
}
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+115
View File
@@ -0,0 +1,115 @@
// This is an example of an NTP client.
//
// It creates a UDP connection to request the current time and parse the
// response from a NTP server. The system time is set to NTP time.
//go:build ninafw || wioterminal || challenger_rp2040
package main
import (
"fmt"
"io"
"log"
"machine"
"net"
"runtime"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
// IP address of the server aka "hub". Replace with your own info.
ntpHost string = "0.pool.ntp.org:123"
)
const NTP_PACKET_SIZE = 48
var response = make([]byte, NTP_PACKET_SIZE)
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
conn, err := net.Dial("udp", ntpHost)
if err != nil {
log.Fatal(err)
}
println("Requesting NTP time...")
t, err := getCurrentTime(conn)
if err != nil {
log.Fatal(fmt.Sprintf("Error getting current time: %v", err))
} else {
message("NTP time: %v", t)
}
conn.Close()
link.NetDisconnect()
runtime.AdjustTimeOffset(-1 * int64(time.Since(t)))
for {
message("Current time: %v", time.Now())
time.Sleep(time.Minute)
}
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
func getCurrentTime(conn net.Conn) (time.Time, error) {
if err := sendNTPpacket(conn); err != nil {
return time.Time{}, err
}
n, err := conn.Read(response)
if err != nil && err != io.EOF {
return time.Time{}, err
}
if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(response), nil
}
func sendNTPpacket(conn net.Conn) error {
var request = [48]byte{
0xe3,
}
_, err := conn.Write(request[:])
return err
}
func parseNTPpacket(r []byte) time.Time {
// the timestamp starts at byte 40 of the received packet and is four bytes,
// this is NTP time (seconds since Jan 1 1900):
t := uint32(r[40])<<24 | uint32(r[41])<<16 | uint32(r[42])<<8 | uint32(r[43])
const seventyYears = 2208988800
return time.Unix(int64(t-seventyYears), 0)
}
func message(format string, args ...interface{}) {
println(fmt.Sprintf(format, args...), "\r")
}
+30
View File
@@ -0,0 +1,30 @@
//go:build ninafw || wioterminal
package main
import (
"log"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
)
func init() {
time.Sleep(2 * time.Second)
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
}
+120
View File
@@ -0,0 +1,120 @@
// This example is the classic snake network test. The snake is feed a steady
// diet of pkts and the pkts work themselves thru the snake segments and exit
// the tail. Each snake segment is a TCP socket connection to a server. The
// server echos pkts received back to the snake, and serves each segment on a
// different port. (See server/main.go for server).
//
// snake | server
// |
// head ----->---|-->--+
// seg a | |
// +---<-|--<--+
// | |
// +-->--|-->--+
// seg b | |
// +---<-|--<--+
// | |
// +-->--|-->--+
// seg c | |
// +---<-|--<--+
// | |
// +-->--|-->--+
// ... | |
// +---<-|--<--+
// | |
// +-->--|-->--+
// seg n | |
// tail -------<-|--<--+
// |
// The snake segments are linked by channels and each segment is run as a go
// func. This forces segments to connect and run concurrently, which is a good
// test of the underlying driver's ability to handle concurrent connections.
//go:build ninafw || wioterminal
package main
import (
_ "embed"
"fmt"
"log"
"net"
"strings"
"time"
)
//go:embed main.go
var code string
var (
server string = "10.0.0.100:8080"
)
func segment(in chan []byte, out chan []byte) {
var buf [512]byte
for {
c, err := net.Dial("tcp", server)
for ; err != nil; c, err = net.Dial("tcp", server) {
println(err.Error())
time.Sleep(5 * time.Second)
}
for {
select {
case msg := <-in:
_, err := c.Write(msg)
if err != nil {
log.Fatal(err.Error())
}
time.Sleep(100 * time.Millisecond)
n, err := c.Read(buf[:])
if err != nil {
log.Fatal(err.Error())
}
out <- buf[:n]
}
}
}
}
func feedit(head chan []byte) {
for i := 0; i < 100; i++ {
head <- []byte(fmt.Sprintf("\n---%d---\n", i))
for _, line := range strings.Split(code, "\n") {
if len(line) == 0 {
line = " "
}
head <- []byte(line)
}
}
}
var head = make(chan []byte)
var a = make(chan []byte)
var b = make(chan []byte)
var c = make(chan []byte)
var d = make(chan []byte)
var e = make(chan []byte)
var f = make(chan []byte)
var tail = make(chan []byte)
func main() {
// The snake
go segment(head, a)
go segment(a, b)
go segment(b, c)
go segment(c, d)
go segment(d, e)
go segment(e, f)
go segment(f, tail)
go feedit(head)
for {
select {
case msg := <-tail:
println(string(msg))
}
}
}
+34
View File
@@ -0,0 +1,34 @@
package main
import (
"io"
"log"
"net"
)
func main() {
// Listen for connections
l, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err.Error())
}
defer l.Close()
println("Listening on port", ":8080")
for {
// Wait for a connection
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
println("Accepted connection from", conn.RemoteAddr().String())
// Service the new connection in a goroutine.
// The loop then returns to accepting, so that
// multiple connections may be served concurrently
go func(c net.Conn) {
// Echo all incoming data
io.Copy(c, c)
// Shut down the connection
c.Close()
}(conn)
}
}
+108
View File
@@ -0,0 +1,108 @@
// This example opens a TCP connection and sends some data using netdev sockets.
//
// You can open a server to accept connections from this program using:
//
// nc -lk 8080
//go:build ninafw || wioterminal || challenger_rp2040
package main
import (
"bytes"
"fmt"
"log"
"machine"
"net/netip"
"time"
"tinygo.org/x/drivers/netdev"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
addr string = "10.0.0.100:8080"
)
var buf = &bytes.Buffer{}
var link netlink.Netlinker
var dev netdev.Netdever
func main() {
waitSerial()
link, dev = probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
}
func sendBatch() {
addrPort, _ := netip.ParseAddrPort(addr)
// make TCP connection
message("---------------\r\nDialing TCP connection")
fd, _ := dev.Socket(netdev.AF_INET, netdev.SOCK_STREAM, netdev.IPPROTO_TCP)
err := dev.Connect(fd, "", addrPort)
for ; err != nil; err = dev.Connect(fd, "", addrPort) {
message(err.Error())
time.Sleep(5 * time.Second)
}
n := 0
w := 0
start := time.Now()
// send data
message("Sending data")
for i := 0; i < 1000; i++ {
buf.Reset()
fmt.Fprint(buf,
"\r---------------------------- i == ", i, " ----------------------------"+
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = dev.Send(fd, buf.Bytes(), 0, time.Time{}); err != nil {
println("error:", err.Error(), "\r")
break
}
n += w
}
buf.Reset()
ms := time.Now().Sub(start).Milliseconds()
fmt.Fprint(buf, "\nWrote ", n, " bytes in ", ms, " ms\r\n")
message(buf.String())
if _, err := dev.Send(fd, buf.Bytes(), 0, time.Time{}); err != nil {
println("error:", err.Error(), "\r")
}
println("Disconnecting TCP...")
dev.Close(fd)
}
func message(msg string) {
println(msg, "\r")
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
@@ -1,52 +1,60 @@
// This example opens a TCP connection and sends some data,
// for the purpose of testing speed and connectivity.
// This example opens a TCP connection and sends some data, for the purpose of
// testing speed and connectivity.
//
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
// nc -lk 8080
//go:build ninafw || wioterminal || challenger_rp2040 || pico
package main
import (
"bytes"
"fmt"
"log"
"machine"
"net"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
// access point info
ssid string
pass string
addr string = "10.0.0.100:8080"
)
// IP address of the server aka "hub". Replace with your own info.
const serverIP = ""
var buf = &bytes.Buffer{}
func main() {
initAdaptor()
connectToAP()
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
println("Done.")
}
func sendBatch() {
// make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
message("---------------\r\nDialing TCP connection")
conn, err := net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
conn, err := net.Dial("tcp", addr)
for ; err != nil; conn, err = net.Dial("tcp", addr) {
message(err.Error())
time.Sleep(5 * time.Second)
}
@@ -65,7 +73,7 @@ func sendBatch() {
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
continue
break
}
n += w
}
@@ -79,34 +87,17 @@ func sendBatch() {
println("error:", err.Error(), "\r")
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil { // error connecting to AP
for {
println(err)
time.Sleep(1 * time.Second)
}
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, err := adaptor.GetClientIP()
for ; err != nil; ip, err = adaptor.GetClientIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message(ip)
}
func message(msg string) {
println(msg, "\r")
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
+70
View File
@@ -0,0 +1,70 @@
// This example listens on port :8080 for client connections. Bytes
// received from the client are echo'ed back to the client. Multiple
// clients can connect as the same time, each consuming a client socket,
// and being serviced by it's own go func.
//
// Example test using nc as client to copy file:
//
// $ nc 10.0.0.2 8080 <file >copy ; cmp file copy
//go:build ninafw || wioterminal
package main
import (
"io"
"log"
"net"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
port string = ":8080"
)
var buf [1024]byte
func echo(conn net.Conn) {
println("Client", conn.RemoteAddr(), "connected")
defer conn.Close()
_, err := io.CopyBuffer(conn, conn, buf[:])
if err != nil && err != io.EOF {
log.Fatal(err.Error())
}
println("Client", conn.RemoteAddr(), "closed")
}
func main() {
time.Sleep(2 * time.Second)
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
println("Starting TCP server listening on", port)
l, err := net.Listen("tcp", port)
if err != nil {
log.Fatal(err.Error())
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
log.Fatal(err.Error())
}
go echo(conn)
}
}
+106
View File
@@ -0,0 +1,106 @@
// This example uses TLS to send an HTTPS request to retrieve a webpage
//
// You shall see "strict-transport-security" header in the response,
// this confirms communication is indeed over HTTPS
//
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
//go:build ninafw || wioterminal
package main
import (
"bufio"
"crypto/tls"
"fmt"
"io"
"log"
"machine"
"net"
"strings"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
// HTTPS server address to hit with a GET / request
address string = "httpbin.org:443"
)
var conn net.Conn
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
func check(err error) {
if err != nil {
println("Hit an error:", err.Error())
panic("BYE")
}
}
func readResponse() {
r := bufio.NewReader(conn)
resp, err := io.ReadAll(r)
check(err)
println(string(resp))
}
func closeConnection() {
conn.Close()
}
func dialConnection() {
var err error
println("\r\n---------------\r\nDialing TLS connection")
conn, err = tls.Dial("tcp", address, nil)
for ; err != nil; conn, err = tls.Dial("tcp", address, nil) {
println("Connection failed:", err.Error())
time.Sleep(5 * time.Second)
}
println("Connected!\r")
}
func makeRequest() {
print("Sending HTTPS request...")
w := bufio.NewWriter(conn)
fmt.Fprintln(w, "GET /get HTTP/1.1")
fmt.Fprintln(w, "Host:", strings.Split(address, ":")[0])
fmt.Fprintln(w, "User-Agent: TinyGo")
fmt.Fprintln(w, "Connection: close")
fmt.Fprintln(w)
check(w.Flush())
println("Sent!\r\n\r")
}
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
for i := 0; ; i++ {
dialConnection()
makeRequest()
readResponse()
closeConnection()
println("--------", i, "--------\r\n")
time.Sleep(10 * time.Second)
}
}
+120
View File
@@ -0,0 +1,120 @@
// This example runs on wioterminal. It gets an URL using http.Get() and
// displays the output on the wioterminal LCD screen.
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//go:build wioterminal
package main
import (
"fmt"
"image/color"
"io"
"log"
"machine"
"net/http"
"net/url"
"strings"
"time"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
"tinygo.org/x/tinyfont/proggy"
"tinygo.org/x/tinyterm"
)
var (
ssid string
pass string
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
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
)
func main() {
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{})
display.FillScreen(black)
backlight.Configure(machine.PinConfig{machine.PinOutput})
backlight.High()
terminal.Configure(&tinyterm.Config{
Font: font,
FontHeight: 10,
FontOffset: 6,
})
fmt.Fprintf(terminal, "Connecting to %s...\r\n", ssid)
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
name := "John Doe"
occupation := "gardener"
params := "name=" + url.QueryEscape(name) + "&" +
"occupation=" + url.QueryEscape(occupation)
path := fmt.Sprintf("https://httpbin.org/get?%s", params)
cnt := 0
for {
fmt.Fprintf(terminal, "Getting %s\r\n\r\n", path)
resp, err := http.Get(path)
if err != nil {
fmt.Fprintf(terminal, "%s\r\n", err.Error())
time.Sleep(10 * time.Second)
continue
}
fmt.Fprintf(terminal, "%s %s\r\n", resp.Proto, resp.Status)
for k, v := range resp.Header {
fmt.Fprintf(terminal, "%s: %s\r\n", k, strings.Join(v, " "))
}
fmt.Fprintf(terminal, "\r\n")
body, err := io.ReadAll(resp.Body)
fmt.Fprintf(terminal, string(body))
resp.Body.Close()
cnt++
fmt.Fprintf(terminal, "-------- %d --------\r\n", cnt)
time.Sleep(10 * time.Second)
}
}
+117
View File
@@ -0,0 +1,117 @@
// This example uses TCP to send an HTTP request to retrieve a webpage. The
// HTTP request is hand-rolled to avoid the overhead of using http.Get() from
// the "net/http" package. See example/net/http-get for the full http.Get()
// functionality.
//
// Example HTTP server:
// ---------------------------------------------------------------------------
// package main
//
// import "net/http"
//
// func main() {
// http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// w.Write([]byte("hello"))
// })
// http.ListenAndServe(":8080", nil)
// }
// ---------------------------------------------------------------------------
//go:build ninafw || wioterminal
package main
import (
"bufio"
"fmt"
"io"
"log"
"machine"
"net"
"strings"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
// HTTP server address to hit with a GET / request
address string = "10.0.0.100:8080"
)
var conn net.Conn
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
func dialConnection() {
var err error
println("\r\n---------------\r\nDialing TCP connection")
conn, err = net.Dial("tcp", address)
for ; err != nil; conn, err = net.Dial("tcp", address) {
println("Connection failed:", err.Error())
time.Sleep(5 * time.Second)
}
println("Connected!\r")
}
func check(err error) {
if err != nil {
println("Hit an error:", err.Error())
panic("BYE")
}
}
func makeRequest() {
println("Sending HTTP request...")
w := bufio.NewWriter(conn)
fmt.Fprintln(w, "GET / HTTP/1.1")
fmt.Fprintln(w, "Host:", strings.Split(address, ":")[0])
fmt.Fprintln(w, "User-Agent: TinyGo")
fmt.Fprintln(w, "Connection: close")
fmt.Fprintln(w)
check(w.Flush())
println("Sent!\r\n\r")
}
func readResponse() {
r := bufio.NewReader(conn)
resp, err := io.ReadAll(r)
check(err)
println(string(resp))
}
func closeConnection() {
conn.Close()
}
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
for i := 0; ; i++ {
dialConnection()
makeRequest()
readResponse()
closeConnection()
println("--------", i, "--------\r\n")
time.Sleep(10 * time.Second)
}
}
@@ -1,72 +1,64 @@
// This example listens on port :80 serving a web page. Multiple clients
// may connect and be serviced at the same time. IPv4 only. HTTP only.
//
// $ curl http://10.0.0.2
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//go:build ninafw || wioterminal
package main
import (
"fmt"
"log"
"machine"
"net/http"
"strconv"
"time"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// debug = true
// }
var (
ssid string
pass string
debug = false
ssid string
pass string
port string = ":80"
)
var led = machine.LED
var backlight = machine.LCD_BACKLIGHT
func main() {
// wait a bit for serial
time.Sleep(2 * time.Second)
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
backlight.Configure(machine.PinConfig{Mode: machine.PinOutput})
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
link, _ := probe.Probe()
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
http.UseDriver(adaptor)
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
return err
log.Fatal(err)
}
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.HandleFunc("/", root)
http.HandleFunc("/hello", hello)
http.HandleFunc("/cnt", cnt)
http.HandleFunc("/6", sixlines)
http.HandleFunc("/off", LED_OFF)
http.HandleFunc("/on", LED_ON)
if err := http.ListenAndServe(":80", nil); err != nil {
message(err.Error())
err = http.ListenAndServe(port, nil)
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
return nil
}
func root(w http.ResponseWriter, r *http.Request) {
@@ -101,8 +93,8 @@ func root(w http.ResponseWriter, r *http.Request) {
<title>TinyGo HTTP Server</title>
<script language="javascript" type="text/javascript">
var counter = 0
function ledOn() { fetch("/on").then(response => response.text()).then(text => { led.innerHTML = "<p>on</p>"; }); }
function ledOff() { fetch("/off").then(response => response.text()).then(text => { led.innerHTML = "<p>off</p>"; }); }
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", {
@@ -141,7 +133,7 @@ func root(w http.ResponseWriter, r *http.Request) {
</p>
</body>
</html>
`, access)
`, access)
}
func sixlines(w http.ResponseWriter, r *http.Request) {
@@ -155,14 +147,12 @@ func sixlines(w http.ResponseWriter, r *http.Request) {
func LED_ON(w http.ResponseWriter, r *http.Request) {
led.High()
backlight.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()
backlight.Low()
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
fmt.Fprintf(w, "led.Low()")
}
@@ -187,7 +177,3 @@ func cnt(w http.ResponseWriter, r *http.Request) {
w.Header().Set(`Content-Type`, `application/json`)
fmt.Fprintf(w, `{"cnt": %d}`, counter)
}
func message(msg string) {
println(msg, "\r")
}
+64
View File
@@ -0,0 +1,64 @@
// This example is a websocket client. It connects to a websocket server
// which echos messages back to the client. For server, see
//
// https://pkg.go.dev/golang.org/x/net/websocket#example-Handler
//
// Note: It may be necessary to increase the stack size when using
// "golang.org/x/net/websocket". Use the -stack-size=4KB command line option.
//go:build ninafw || wioterminal
package main
import (
"fmt"
"log"
"machine"
"time"
"golang.org/x/net/websocket"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
url string = "ws://10.0.0.100:8080/echo"
)
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
origin := "http://localhost/"
ws, err := websocket.Dial(url, "", origin)
if err != nil {
log.Fatal(err)
}
if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
log.Fatal(err)
}
var msg = make([]byte, 512)
var n int
if n, err = ws.Read(msg); err != nil {
log.Fatal(err)
}
fmt.Printf("Received: %s", msg[:n])
}
+62
View File
@@ -0,0 +1,62 @@
// This example is a websocket server. It listens for websocket clients
// to connect and echos messages back to the client. For client, see
//
// https://pkg.go.dev/golang.org/x/net/websocket#example-Dial
//
// Note: It may be necessary to increase the stack size when using
// "golang.org/x/net/websocket". Use the -stack-size=4KB command line option.
//go:build ninafw || wioterminal
package main
import (
"io"
"log"
"machine"
"net/http"
"time"
"golang.org/x/net/websocket"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
port string = ":8080"
)
// Echo the data received on the WebSocket.
func EchoServer(ws *websocket.Conn) {
io.Copy(ws, ws)
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
// This example demonstrates a trivial echo server.
func main() {
waitSerial()
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
http.Handle("/echo", websocket.Handler(EchoServer))
err = http.ListenAndServe(port, nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

+28
View File
@@ -0,0 +1,28 @@
<html>
<head>
<title>TinyGo - A Go Compiler For Small Places</title>
<style>
body {
background-color: rgb(4, 111, 143);
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
img {
display: block;
margin: 0 auto;
width: 299px;
height: 255px;
}
h1 {
color: white;
text-align: center;
}
</style>
</head>
<body>
<h1>TinyGo - A Go Compiler For Small Places</h1>
<img src="images/tinygo-logo.png">
</body>
</html>
+49
View File
@@ -0,0 +1,49 @@
// This example is an HTTP server serving up a static file system
//
// Note: It may be necessary to increase the stack size when using "net/http".
// Use the -stack-size=4KB command line option.
//go:build ninafw || wioterminal
package main
import (
"embed"
"log"
"net/http"
"time"
"tinygo.org/x/drivers/netlink"
"tinygo.org/x/drivers/netlink/probe"
)
var (
ssid string
pass string
port string = ":80"
)
//go:embed index.html main.go images
var fs embed.FS
func main() {
// wait a bit for console
time.Sleep(2 * time.Second)
link, _ := probe.Probe()
err := link.NetConnect(&netlink.ConnectParams{
Ssid: ssid,
Passphrase: pass,
})
if err != nil {
log.Fatal(err)
}
hfs := http.FileServer(http.FS(fs))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
hfs.ServeHTTP(w, r)
})
log.Fatal(http.ListenAndServe(port, nil))
}
+28
View File
@@ -0,0 +1,28 @@
// Connects to a pcf8591 ADC via I2C.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/pcf8591"
)
var (
i2c = machine.I2C0
)
func main() {
i2c.Configure(machine.I2CConfig{})
adc := pcf8591.New(i2c)
adc.Configure()
// get "CH0" aka "machine.ADC" interface to channel 0 from ADC.
p := adc.CH0
for {
val := p.Get()
println(val)
time.Sleep(50 * time.Millisecond)
}
}
-131
View File
@@ -1,131 +0,0 @@
// This is a sensor station that uses a RTL8720DN running on the device UART2.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> USB-CDC <--> MCU <--> UART2 <--> RTL8720DN <--> Internet <--> MQTT broker.
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
// You can check that mqttpub is running successfully with the following command.
//
// mosquitto_sub -h test.mosquitto.org -t tinygo
package main
import (
"machine"
"fmt"
"math/rand"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// debug = true
// server = "tinygo.org"
// }
var (
ssid string
pass string
server string = "tcp://test.mosquitto.org:1883"
debug = false
)
var buf [0x400]byte
var lastRequestTime time.Time
var conn net.Conn
var adaptor *rtl8720dn.Driver
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
var (
topic = "tinygo"
)
func run() error {
// change the UART and pins as needed for platforms other than the WioTerminal.
adaptor = rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
rand.Seed(time.Now().UnixNano())
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connectng to MQTT...")
cl := mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topic, 0, false, data)
token.Wait()
if err := token.Error(); err != nil {
return err
}
time.Sleep(100 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
return nil
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-154
View File
@@ -1,154 +0,0 @@
// This is a sensor station that uses a RTL8720DN running on the device UART2.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> USB-CDC <--> MCU <--> UART2 <--> RTL8720DN <--> Internet <--> MQTT broker.
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
// You can check that mqttpub/mqttsub is running successfully with the following command.
//
// mosquitto_sub -h test.mosquitto.org -t tinygo/tx
// mosquitto_pub -h test.mosquitto.org -t tinygo/rx -m "hello world"
package main
import (
"machine"
"fmt"
"math/rand"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// debug = true
// server = "tinygo.org"
// }
var (
ssid string
pass string
server string = "tcp://test.mosquitto.org:1883"
debug = false
)
var buf [0x400]byte
var lastRequestTime time.Time
var conn net.Conn
var adaptor *rtl8720dn.Driver
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
cl mqtt.Client
topicTx = "tinygo/tx"
topicRx = "tinygo/rx"
)
func subHandler(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("[%s] ", msg.Topic())
fmt.Printf("%s\r\n", msg.Payload())
}
func run() error {
// change the UART and pins as needed for platforms other than the WioTerminal.
adaptor = rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
rand.Seed(time.Now().UnixNano())
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl = mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
// subscribe
token := cl.Subscribe(topicRx, 0, subHandler)
token.Wait()
if token.Error() != nil {
failMessage(token.Error().Error())
}
go publishing()
select {}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
return nil
}
func publishing() {
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topicTx, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(20 * 100 * time.Millisecond)
}
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-143
View File
@@ -1,143 +0,0 @@
// This is an example of using the rtl8720dn driver to implement a NTP client.
// It creates a UDP connection to request the current time and parse the
// response from a NTP server.
package main
import (
"machine"
"errors"
"fmt"
"runtime"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/rtl8720dn"
)
// IP address of the server aka "hub". Replace with your own info.
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// ntpHost = "129.6.15.29"
// debug = true
// }
var (
ssid string
pass string
ntpHost = "129.6.15.29"
debug = false
)
const NTP_PACKET_SIZE = 48
var b = make([]byte, NTP_PACKET_SIZE)
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
// now make UDP connection
hip := net.ParseIP(ntpHost)
raddr := &net.UDPAddr{IP: hip, Port: 123}
laddr := &net.UDPAddr{Port: 2390}
conn, err := net.DialUDP("udp", laddr, raddr)
if err != nil {
return err
}
for {
// send data
println("Requesting NTP time...")
t, err := getCurrentTime(conn)
if err != nil {
message("Error getting current time: %v", err)
} else {
message("NTP time: %v", t)
}
runtime.AdjustTimeOffset(-1 * int64(time.Since(t)))
for i := 0; i < 10; i++ {
message("Current time: %v", time.Now())
time.Sleep(1 * time.Second)
}
}
}
func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
if err := sendNTPpacket(conn); err != nil {
return time.Time{}, err
}
clearBuffer()
for now := time.Now(); time.Since(now) < time.Second; {
time.Sleep(5 * time.Millisecond)
if n, err := conn.Read(b); err != nil {
return time.Time{}, fmt.Errorf("error reading UDP packet: %w", err)
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(), nil
}
return time.Time{}, errors.New("no packet received after 1 second")
}
func sendNTPpacket(conn *net.UDPSerialConn) error {
clearBuffer()
b[0] = 0b11100011 // LI, Version, Mode
b[1] = 0 // Stratum, or type of clock
b[2] = 6 // Polling Interval
b[3] = 0xEC // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
b[12] = 49
b[13] = 0x4E
b[14] = 49
b[15] = 52
if _, err := conn.Write(b); err != nil {
return err
}
return nil
}
func parseNTPpacket() time.Time {
// the timestamp starts at byte 40 of the received packet and is four bytes,
// this is NTP time (seconds since Jan 1 1900):
t := uint32(b[40])<<24 | uint32(b[41])<<16 | uint32(b[42])<<8 | uint32(b[43])
const seventyYears = 2208988800
return time.Unix(int64(t-seventyYears), 0)
}
func clearBuffer() {
for i := range b {
b[i] = 0
}
}
func message(format string, args ...interface{}) {
println(fmt.Sprintf(format, args...), "\r")
}
-121
View File
@@ -1,121 +0,0 @@
// This example opens a TCP connection using a device with RTL8720DN firmware
// and sends some data, for the purpose of testing speed and connectivity.
//
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
package main
import (
"machine"
"bytes"
"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"
// pass = "your-password"
// serverIP = "192.168.1.119"
// debug = true
// }
var (
ssid string
pass string
serverIP = ""
debug = false
)
var buf = &bytes.Buffer{}
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
println("Done.")
return nil
}
func sendBatch() {
// make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
message("---------------\r\nDialing TCP connection")
conn, err := net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
message(err.Error())
time.Sleep(5 * time.Second)
}
n := 0
w := 0
start := time.Now()
// send data
message("Sending data")
for i := 0; i < 1000; i++ {
buf.Reset()
fmt.Fprint(buf,
"\r---------------------------- i == ", i, " ----------------------------"+
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
continue
}
n += w
}
buf.Reset()
ms := time.Now().Sub(start).Milliseconds()
fmt.Fprint(buf, "\nWrote ", n, " bytes in ", ms, " ms\r\n")
message(buf.String())
if _, err := conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
}
func message(msg string) {
println(msg, "\r")
}
-137
View File
@@ -1,137 +0,0 @@
package main
import (
"machine"
"bufio"
"fmt"
"strings"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// debug = true
// url = "https://www.example.com"
// test_root_ca = "..."
// }
var (
ssid string
pass string
url string = "https://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 [0x1000]byte
var lastRequestTime time.Time
var conn net.Conn
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
adaptor.SetRootCA(&test_root_ca)
http.SetBuf(buf[:])
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
// You can send and receive cookies in the following way
// import "tinygo.org/x/drivers/net/http/cookiejar"
// jar, err := cookiejar.New(nil)
// if err != nil {
// return err
// }
// client := &http.Client{Jar: jar}
// http.DefaultClient = client
cnt := 0
for {
// Various examples are as follows
//
// -- Get
// resp, err := http.Get(url)
//
// -- Post
// body := `cnt=12`
// resp, err = http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(body))
//
// -- Post with JSON
// body := `{"msg": "hello"}`
// resp, err := http.Post(url, "application/json", strings.NewReader(body))
resp, err := http.Get(url)
if err != nil {
return err
}
fmt.Printf("%s %s\r\n", resp.Proto, resp.Status)
for k, v := range resp.Header {
fmt.Printf("%s: %s\r\n", k, strings.Join(v, " "))
}
fmt.Printf("\r\n")
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
fmt.Printf("%s\r\n", scanner.Text())
}
resp.Body.Close()
cnt++
fmt.Printf("-------- %d --------\r\n", cnt)
time.Sleep(10 * time.Second)
}
}
-91
View File
@@ -1,91 +0,0 @@
package main
import (
"machine"
"fmt"
"strconv"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
)
// IP address of the server aka "hub". Replace with your own info.
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// hubIP = "192.168.1.118"
// debug = true
// }
var (
ssid string
pass string
hubIP = ""
debug = false
)
var buf [0x400]byte
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
http.SetBuf(buf[:])
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
// now make UDP connection
hip := net.ParseIP(hubIP)
raddr := &net.UDPAddr{IP: hip, Port: 2222}
laddr := &net.UDPAddr{Port: 2222}
println("Dialing UDP connection...")
conn, err := net.DialUDP("udp", laddr, raddr)
if err != nil {
return err
}
for {
// send data
println("Sending data...")
for i := 0; i < 25; i++ {
conn.Write([]byte("hello " + strconv.Itoa(i) + "\r\n"))
}
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting UDP...")
conn.Close()
println("Done.")
return nil
}
func message(msg string) {
println(msg, "\r")
}
-40
View File
@@ -1,40 +0,0 @@
package main
import (
"machine"
"fmt"
"time"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
debug = false
)
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
ver, err := adaptor.Version()
if err != nil {
return nil
}
for {
fmt.Printf("RTL8270DN Firmware Version: %s\r\n", ver)
time.Sleep(10 * time.Second)
}
return nil
}
@@ -1,162 +0,0 @@
package main
import (
"machine"
"bufio"
"fmt"
"image/color"
"strings"
"time"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/net/http"
"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.
// If debug is enabled, a serial connection is required.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// debug = false // true
// server = "tinygo.org"
// }
var (
ssid string
pass string
url = "http://tinygo.org/"
debug = false
)
var (
display = ili9341.NewSPI(
machine.SPI3,
machine.LCD_DC,
machine.LCD_SS_PIN,
machine.LCD_RESET,
)
backlight = machine.LCD_BACKLIGHT
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
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")
if debug {
fmt.Fprintf(terminal, "Running in debug mode.\r\n")
fmt.Fprintf(terminal, "A serial connection is required to continue execution.\r\n")
}
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
http.UseDriver(adaptor)
http.SetBuf(buf[:])
fmt.Fprintf(terminal, "ConnectToAP()\r\n")
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
fmt.Fprintf(terminal, "connected\r\n\r\n")
ip, subnet, gateway, err := adaptor.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)
// You can send and receive cookies in the following way
// import "tinygo.org/x/drivers/net/http/cookiejar"
// jar, err := cookiejar.New(nil)
// if err != nil {
// return err
// }
// client := &http.Client{Jar: jar}
// http.DefaultClient = client
cnt := 0
for {
// Various examples are as follows
//
// -- Get
// resp, err := http.Get(url)
//
// -- Post
// body := `cnt=12`
// resp, err = http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(body))
//
// -- Post with JSON
// body := `{"msg": "hello"}`
// resp, err := http.Post(url, "application/json", strings.NewReader(body))
resp, err := http.Get(url)
if err != nil {
return err
}
fmt.Fprintf(terminal, "%s %s\r\n", resp.Proto, resp.Status)
for k, v := range resp.Header {
fmt.Fprintf(terminal, "%s: %s\r\n", k, strings.Join(v, " "))
}
fmt.Printf("\r\n")
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
fmt.Fprintf(terminal, "%s\r\n", scanner.Text())
}
resp.Body.Close()
cnt++
fmt.Fprintf(terminal, "-------- %d --------\r\n", cnt)
time.Sleep(10 * time.Second)
}
}
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})
}
-106
View File
@@ -1,106 +0,0 @@
package main
import (
"machine"
"bufio"
"fmt"
"strings"
"time"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/rtl8720dn"
)
// You can override the setting with the init() in another source code.
// func init() {
// ssid = "your-ssid"
// pass = "your-password"
// url = "http://tinygo.org/"
// debug = true
// }
var (
ssid string
pass string
url = "http://tinygo.org/"
debug = false
)
var buf [0x400]byte
func main() {
err := run()
for err != nil {
fmt.Printf("error: %s\r\n", err.Error())
time.Sleep(5 * time.Second)
}
}
func run() error {
adaptor := rtl8720dn.New(machine.UART3, machine.PB24, machine.PC24, machine.RTL8720D_CHIP_PU)
adaptor.Debug(debug)
adaptor.Configure()
http.UseDriver(adaptor)
http.SetBuf(buf[:])
err := adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err != nil {
return err
}
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)
// You can send and receive cookies in the following way
// import "tinygo.org/x/drivers/net/http/cookiejar"
// jar, err := cookiejar.New(nil)
// if err != nil {
// return err
// }
// client := &http.Client{Jar: jar}
// http.DefaultClient = client
cnt := 0
for {
// Various examples are as follows
//
// -- Get
// resp, err := http.Get(url)
//
// -- Post
// body := `cnt=12`
// resp, err = http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(body))
//
// -- Post with JSON
// body := `{"msg": "hello"}`
// resp, err := http.Post(url, "application/json", strings.NewReader(body))
resp, err := http.Get(url)
if err != nil {
return err
}
fmt.Printf("%s %s\r\n", resp.Proto, resp.Status)
for k, v := range resp.Header {
fmt.Printf("%s: %s\r\n", k, strings.Join(v, " "))
}
fmt.Printf("\r\n")
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
fmt.Printf("%s\r\n", scanner.Text())
}
resp.Body.Close()
cnt++
fmt.Printf("-------- %d --------\r\n", cnt)
time.Sleep(10 * time.Second)
}
}
+33
View File
@@ -0,0 +1,33 @@
package main
import (
"machine"
"strconv"
"time"
"tinygo.org/x/drivers/seesaw"
)
const readDelay = time.Microsecond * 3000
// example reading soil moisture with an Adafruit capacitive soil-sensor (4026) powered by a seesaw
// https://learn.adafruit.com/adafruit-stemma-soil-sensor-i2c-capacitive-moisture-sensor/overview
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
dev := seesaw.New(machine.I2C0)
dev.Address = 0x36
// the soil sensor is especially slow, let's give it some more time
dev.ReadDelay = readDelay
var buf [2]byte
err := dev.Read(seesaw.ModuleTouchBase, seesaw.FunctionTouchChannelOffset, buf[:])
if err != nil {
panic(err)
}
moisture := uint16(buf[0])<<8 | uint16(buf[1])
println("soil moisture: " + strconv.Itoa(int(moisture)))
}
+19 -13
View File
@@ -25,19 +25,25 @@ func main() {
return
}
println("setting to 0°")
s.SetMicroseconds(1000)
time.Sleep(3 * time.Second)
println("setting to 45°")
s.SetMicroseconds(1500)
time.Sleep(3 * time.Second)
println("setting to 90°")
s.SetMicroseconds(2000)
time.Sleep(3 * time.Second)
for {
time.Sleep(time.Second)
println("setting to 0°")
s.SetAngle(0)
time.Sleep(3 * time.Second)
println("setting to 45°")
s.SetAngle(45)
time.Sleep(3 * time.Second)
println("setting to 90°")
s.SetAngle(90)
time.Sleep(3 * time.Second)
println("setting to 135°")
s.SetAngle(135)
time.Sleep(3 * time.Second)
println("setting to 180°")
s.SetAngle(180)
time.Sleep(3 * time.Second)
}
}
+53
View File
@@ -0,0 +1,53 @@
package main
// Example for the SGP30 to be used on a Raspberry Pi pico.
// Connect the sensor I2C pins to GP26 and GP27 to test.
import (
"machine"
"time"
"tinygo.org/x/drivers/sgp30"
)
func main() {
time.Sleep(time.Second)
println("start")
// Configure the I2C bus.
bus := machine.I2C1
err := bus.Configure(machine.I2CConfig{
SDA: machine.GP26,
SCL: machine.GP27,
Frequency: 400 * machine.KHz,
})
if err != nil {
println("could not configure I2C:", bus)
return
}
// Configure the sensor.
sensor := sgp30.New(bus)
if !sensor.Connected() {
println("sensor not connected")
return
}
err = sensor.Configure(sgp30.Config{})
if err != nil {
println("sensor could not be configured:", err.Error())
return
}
// Measure every second, as recommended by the datasheet.
for {
time.Sleep(time.Second)
err := sensor.Update(0)
if err != nil {
println("could not read sensor:", err.Error())
continue
}
println("CO₂ equivalent:", sensor.CO2())
println("TVOC ", sensor.TVOC())
}
}
+50
View File
@@ -0,0 +1,50 @@
// This example using the SSD1306 OLED display over SPI on the Thumby board
// A very tiny 72x40 display.
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/ssd1306"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{})
display := ssd1306.NewSPI(machine.SPI0, machine.THUMBY_DC_PIN, machine.THUMBY_RESET_PIN, machine.THUMBY_CS_PIN)
display.Configure(ssd1306.Config{
Width: 72,
Height: 40,
ResetCol: ssd1306.ResetValue{28, 99},
ResetPage: ssd1306.ResetValue{0, 5},
})
display.ClearDisplay()
x := int16(36)
y := int16(20)
deltaX := int16(1)
deltaY := int16(1)
for {
pixel := display.GetPixel(x, y)
c := color.RGBA{255, 255, 255, 255}
if pixel {
c = color.RGBA{0, 0, 0, 255}
}
display.SetPixel(x, y, c)
display.Display()
x += deltaX
y += deltaY
if x == 0 || x == 71 {
deltaX = -deltaX
}
if y == 0 || y == 39 {
deltaY = -deltaY
}
time.Sleep(1 * time.Millisecond)
}
}
+40 -12
View File
@@ -3,7 +3,9 @@ package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/uc8151"
)
@@ -14,30 +16,56 @@ func main() {
led = machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 12000000,
Frequency: 12 * machine.MHz,
SCK: machine.EPD_SCK_PIN,
SDO: machine.EPD_SDO_PIN,
})
display = uc8151.New(machine.SPI0, machine.EPD_CS_PIN, machine.EPD_DC_PIN, machine.EPD_RESET_PIN, machine.EPD_BUSY_PIN)
display.Configure(uc8151.Config{
Rotation: uc8151.ROTATION_270,
Speed: uc8151.MEDIUM,
Blocking: true,
Rotation: drivers.Rotation270,
Speed: uc8151.TURBO,
FlickerFree: true,
Blocking: false,
})
black := color.RGBA{1, 1, 1, 255}
display.ClearBuffer()
display.Display()
for i := int16(0); i < 37; i++ {
for j := int16(0); j < 16; j++ {
if (i+j)%2 == 0 {
showRect(i*8, j*8, 8, 8, black)
display.ClearDisplay()
mod := int16(1)
for {
// checkerboard
for i := int16(0); i < 11; i++ {
if mod == 1 {
mod = 0
} else {
mod = 1
}
display.ClearBuffer()
for i := int16(0); i < 37; i++ {
for j := int16(0); j < 16; j++ {
if (i+j)%2 == mod {
showRect(i*8, j*8, 8, 8, black)
}
}
}
display.Display()
time.Sleep(500 * time.Millisecond)
}
// moving line
for i := int16(16); i < 21; i++ {
display.ClearBuffer()
for j := int16(0); j < 16; j++ {
if (i+j)%2 == 0 {
showRect(i*8, j*8, 8, 8, black)
}
display.Display()
time.Sleep(250 * time.Millisecond)
}
}
}
display.Display()
}
func showRect(x int16, y int16, w int16, h int16, c color.RGBA) {
+84
View File
@@ -0,0 +1,84 @@
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/waveshare-epd/epd2in66b"
"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freemono"
)
var (
black = color.RGBA{0, 0, 0, 0xff}
white = color.RGBA{0xff, 0xff, 0xff, 0xff}
red = color.RGBA{0xff, 0, 0, 0xff}
)
func main() {
machine.Serial.Configure(machine.UARTConfig{})
time.Sleep(2 * time.Second)
machine.SPI1.Configure(machine.SPIConfig{
Frequency: epd2in66b.Baudrate,
})
println("started")
// in case you have a Pico module, you can directly use
// dev, err := epd2in66b.NewPicoModule()
display := epd2in66b.New(machine.SPI1)
cfg := epd2in66b.Config{
DataPin: machine.GP8,
ChipSelectPin: machine.GP9,
ResetPin: machine.GP12,
BusyPin: machine.GP13,
}
err := display.Configure(cfg)
if err != nil {
panic(err)
}
err = display.Reset()
if err != nil {
panic(err)
}
println("draw checkerboard")
drawCheckerBoard(&display)
println("draw 'hello'")
tinyfont.WriteLineRotated(&display, &freemono.Bold24pt7b, 40, 10, "Hello!", white, tinyfont.ROTATION_90)
tinyfont.WriteLineRotated(&display, &freemono.Bold12pt7b, 10, 10, "tinygo rocks", white, tinyfont.ROTATION_90)
err = display.Display()
if err != nil {
panic(err)
}
}
func drawCheckerBoard(display drivers.Displayer) {
s := 8
width, height := display.Size()
for x := 0; x <= int(width)-s; x += s {
for y := 0; y <= int(height)-s; y += s {
c := red
if (x/s)%2 == (y/s)%2 {
c = black
}
showRect(display, x, y, s, s, c)
}
}
}
func showRect(display drivers.Displayer, x int, y int, w int, h int, c color.RGBA) {
for i := x; i < x+w; i++ {
for j := y; j < y+h; j++ {
display.SetPixel(int16(i), int16(j), c)
}
}
}
-27
View File
@@ -1,27 +0,0 @@
//go:build espat
package main
import (
"machine"
"tinygo.org/x/drivers/espat"
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func initAdaptor() *espat.Device {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
adaptor = espat.New(uart)
adaptor.Configure()
return adaptor
}
-76
View File
@@ -1,76 +0,0 @@
//go:build rtl8720dn
package main
import (
"device/sam"
"machine"
"runtime/interrupt"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/rtl8720dn"
)
var (
adaptor *rtl8720dn.RTL8720DN
uart UARTx
)
func initAdaptor() *rtl8720dn.RTL8720DN {
adaptor, err := setupRTL8720DN()
if err != nil {
return nil
}
net.UseDriver(adaptor)
return adaptor
}
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)
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
}
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)
}
-35
View File
@@ -1,35 +0,0 @@
//go:build wifinina
package main
import (
"machine"
"tinygo.org/x/drivers/wifinina"
)
var (
// default interface for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// ESP32/ESP8266 chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
func initAdaptor() *wifinina.Device {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
return adaptor
}
-156
View File
@@ -1,156 +0,0 @@
// This example connects to Access Point and prints some info
package main
import (
"machine"
"strconv"
"time"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
}
func main() {
setup()
waitSerial()
connectToAP()
for {
println("----------------------------------------")
printSSID()
printRSSI()
printMac()
printIPs()
printTime()
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 {
println("IP: Unknown (error: ", err.Error(), ")")
return
}
println("IP: ", ip.String())
println("Subnet: ", subnet.String())
println("Gateway: ", gateway.String())
}
func printTime() {
print("Time: ")
t, err := adaptor.GetTime()
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 printMac() {
print("MAC: ")
mac, err := adaptor.GetMACAddress()
if err != nil {
println("Unknown (", err.Error(), ")")
}
println(mac.String())
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-173
View File
@@ -1,173 +0,0 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends a HTTP request to retrieve a webpage, based on the following
// Arduino example:
//
// https://github.com/arduino-libraries/WiFiNINA/blob/master/examples/WiFiWebClientRepeating/
//
// This example will not work with samd21 or other systems with less than 32KB
// of RAM. Use the following if you want to run wifinina on samd21, etc.
//
// examples/wifinina/webclient
// examples/wifinina/tlsclient
package main
import (
"bufio"
"fmt"
"machine"
"strings"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/http"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
// Can specify a URL starting with http or https
const url = "http://tinygo.org/"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
var buf [0x400]byte
var lastRequestTime time.Time
var conn net.Conn
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
}
func main() {
setup()
http.SetBuf(buf[:])
waitSerial()
connectToAP()
displayIP()
// You can send and receive cookies in the following way
// import "tinygo.org/x/drivers/net/http/cookiejar"
// jar, err := cookiejar.New(nil)
// if err != nil {
// return err
// }
// client := &http.Client{Jar: jar}
// http.DefaultClient = client
cnt := 0
for {
// Various examples are as follows
//
// -- Get
// resp, err := http.Get(url)
//
// -- Post
// body := `cnt=12`
// resp, err = http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(body))
//
// -- Post with JSON
// body := `{"msg": "hello"}`
// resp, err := http.Post(url, "application/json", strings.NewReader(body))
resp, err := http.Get(url)
if err != nil {
fmt.Printf("%s\r\n", err.Error())
continue
}
fmt.Printf("%s %s\r\n", resp.Proto, resp.Status)
for k, v := range resp.Header {
fmt.Printf("%s: %s\r\n", k, strings.Join(v, " "))
}
fmt.Printf("\r\n")
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
fmt.Printf("%s\r\n", scanner.Text())
}
resp.Body.Close()
cnt++
fmt.Printf("-------- %d --------\r\n", cnt)
time.Sleep(10 * time.Second)
}
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(msg string) {
println(msg, "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-153
View File
@@ -1,153 +0,0 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
topic = "tinygo"
)
func main() {
time.Sleep(3000 * time.Millisecond)
rand.Seed(time.Now().UnixNano())
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
// Init esp8266/esp32
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
connectToAP()
displayIP()
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connectng to MQTT...")
cl := mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topic, 0, false, data)
token.Wait()
if err := token.Error(); err != nil {
switch t := err.(type) {
case wifinina.Error:
println(t.Error(), "attempting to reconnect")
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
default:
println(err.Error())
}
}
time.Sleep(100 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
time.Sleep(1 * time.Second)
}
println("IP address: " + ip.String())
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-165
View File
@@ -1,165 +0,0 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
cl mqtt.Client
topicTx = "tinygo/tx"
topicRx = "tinygo/rx"
)
func subHandler(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("[%s] ", msg.Topic())
fmt.Printf("%s\r\n", msg.Payload())
}
func main() {
time.Sleep(3000 * time.Millisecond)
rand.Seed(time.Now().UnixNano())
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
// Init esp8266/esp32
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
connectToAP()
displayIP()
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl = mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
// subscribe
token := cl.Subscribe(topicRx, 0, subHandler)
token.Wait()
if token.Error() != nil {
failMessage(token.Error().Error())
}
go publishing()
select {}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
func publishing() {
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topicRx, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(100 * time.Millisecond)
}
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
time.Sleep(1 * time.Second)
}
println("IP address: " + ip.String())
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-191
View File
@@ -1,191 +0,0 @@
// This is an example of using the wifinina driver to implement a NTP client.
// It creates a UDP connection to request the current time and parse the
// response from a NTP server.
package main
import (
"errors"
"fmt"
"machine"
"runtime"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
const ntpHost = "129.6.15.29"
const NTP_PACKET_SIZE = 48
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
b = make([]byte, NTP_PACKET_SIZE)
)
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
}
func main() {
setup()
waitSerial()
connectToAP()
displayIP()
// now make UDP connection
ip := net.ParseIP(ntpHost)
raddr := &net.UDPAddr{IP: ip, Port: 123}
laddr := &net.UDPAddr{Port: 2390}
conn, err := net.DialUDP("udp", laddr, raddr)
if err != nil {
for {
time.Sleep(time.Second)
println(err)
}
}
for {
// send data
println("Requesting NTP time...")
t, err := getCurrentTime(conn)
if err != nil {
message("Error getting current time: %v", err)
} else {
message("NTP time: %v", t)
}
runtime.AdjustTimeOffset(-1 * int64(time.Since(t)))
for i := 0; i < 10; i++ {
message("Current time: %v", time.Now())
time.Sleep(1 * time.Second)
}
}
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
func getCurrentTime(conn *net.UDPSerialConn) (time.Time, error) {
if err := sendNTPpacket(conn); err != nil {
return time.Time{}, err
}
clearBuffer()
for now := time.Now(); time.Since(now) < time.Second; {
time.Sleep(5 * time.Millisecond)
if n, err := conn.Read(b); err != nil {
return time.Time{}, fmt.Errorf("error reading UDP packet: %w", err)
} else if n == 0 {
continue // no packet received yet
} else if n != NTP_PACKET_SIZE {
return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n)
}
return parseNTPpacket(), nil
}
return time.Time{}, errors.New("no packet received after 1 second")
}
func sendNTPpacket(conn *net.UDPSerialConn) error {
clearBuffer()
b[0] = 0b11100011 // LI, Version, Mode
b[1] = 0 // Stratum, or type of clock
b[2] = 6 // Polling Interval
b[3] = 0xEC // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
b[12] = 49
b[13] = 0x4E
b[14] = 49
b[15] = 52
if _, err := conn.Write(b); err != nil {
return err
}
return nil
}
func parseNTPpacket() time.Time {
// the timestamp starts at byte 40 of the received packet and is four bytes,
// this is NTP time (seconds since Jan 1 1900):
t := uint32(b[40])<<24 | uint32(b[41])<<16 | uint32(b[42])<<8 | uint32(b[43])
const seventyYears = 2208988800
return time.Unix(int64(t-seventyYears), 0)
}
func clearBuffer() {
for i := range b {
b[i] = 0
}
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(format string, args ...interface{}) {
println(fmt.Sprintf(format, args...), "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-90
View File
@@ -1,90 +0,0 @@
//go:build nano_rp2040
// This examples shows how to control RGB LED connected to
// NINA-W102 chip on Arduino Nano RP2040 Connect board
// Built-in LED code added for API comparison
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/wifinina"
)
const (
LED = machine.LED
// Arduino Nano RP2040 Connect board RGB LED pins
// See https://docs.arduino.cc/static/3525d638b5c76a2d19588d6b41cd02a0/ABX00053-full-pinout.pdf
LED_R wifinina.Pin = 27
LED_G wifinina.Pin = 25
LED_B wifinina.Pin = 26
)
var (
// these are the default pins for the Arduino Nano-RP2040 Connect
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
device *wifinina.Device
)
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
device = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
device.Configure()
time.Sleep(time.Second)
LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
LED_R.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
LED_G.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
LED_B.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput})
}
func main() {
setup()
LED.Low() // OFF
LED_R.High() // OFF
LED_G.High() // OFF
LED_B.High() // OFF
go func() {
for {
LED.Low()
time.Sleep(time.Second)
LED.High()
time.Sleep(time.Second)
}
}()
for {
LED_R.Low() // ON
time.Sleep(time.Second)
LED_R.High() // OFF
LED_G.Low() // ON
time.Sleep(time.Second)
LED_G.High() // OFF
LED_B.Low() // ON
time.Sleep(time.Second)
LED_B.High() // OFF
}
}
-153
View File
@@ -1,153 +0,0 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends some data, for the purpose of testing speed and connectivity.
//
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
package main
import (
"bytes"
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
const serverIP = ""
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
var buf = &bytes.Buffer{}
func main() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
connectToAP()
displayIP()
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
println("Done.")
}
func sendBatch() {
// make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
message("---------------\r\nDialing TCP connection")
conn, err := net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
message(err.Error())
time.Sleep(5 * time.Second)
}
n := 0
w := 0
start := time.Now()
// send data
message("Sending data")
for i := 0; i < 1000; i++ {
buf.Reset()
fmt.Fprint(buf,
"\r---------------------------- i == ", i, " ----------------------------"+
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
continue
}
n += w
}
buf.Reset()
ms := time.Now().Sub(start).Milliseconds()
fmt.Fprint(buf, "\nWrote ", n, " bytes in ", ms, " ms\r\n")
message(buf.String())
if _, err := conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(msg string) {
println(msg, "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-163
View File
@@ -1,163 +0,0 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends a HTTPS request to retrieve a webpage
//
// You shall see "strict-transport-security" header in the response,
// this confirms communication is indeed over HTTPS
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
package main
import (
"fmt"
"machine"
"strings"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/net/tls"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
const server = "tinygo.org"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
var buf [256]byte
var lastRequestTime time.Time
var conn net.Conn
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
}
func main() {
setup()
waitSerial()
connectToAP()
displayIP()
for {
readConnection()
if time.Now().Sub(lastRequestTime).Milliseconds() >= 10000 {
makeHTTPSRequest()
}
}
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
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()
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(msg string) {
println(msg, "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-119
View File
@@ -1,119 +0,0 @@
// This is a sensor station that uses a ESP32 running nina-fw over SPI.
// It creates a UDP connection you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> SPI <--> ESP32
package main
import (
"machine"
"strconv"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the server aka "hub". Replace with your own info.
const hubIP = ""
var (
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
func main() {
// Init esp8266/esp32
// Configure SPI for 8Mhz, Mode 0, MSB First
machine.NINA_SPI.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
adaptor = wifinina.New(machine.NINA_SPI,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
// connect to access point
connectToAP()
displayIP()
// now make UDP connection
ip := net.ParseIP(hubIP)
raddr := &net.UDPAddr{IP: ip, Port: 2222}
laddr := &net.UDPAddr{Port: 2222}
println("Dialing UDP connection...")
conn, err := net.DialUDP("udp", laddr, raddr)
if err != nil {
failMessage(err.Error())
}
for {
// send data
println("Sending data...")
for i := 0; i < 25; i++ {
conn.Write([]byte("hello " + strconv.Itoa(i) + "\r\n"))
}
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting UDP...")
conn.Close()
println("Done.")
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(msg string) {
println(msg, "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-165
View File
@@ -1,165 +0,0 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends a HTTP request to retrieve a webpage, based on the following
// Arduino example:
//
// https://github.com/arduino-libraries/WiFiNINA/blob/master/examples/WiFiWebClientRepeating/
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
var (
// access point info
ssid string
pass string
)
// IP address of the "example.com" server. Replace with your own info.
const server = "93.184.216.34"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
var buf [256]byte
var lastRequestTime time.Time
var conn net.Conn
func setup() {
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
SDO: machine.NINA_SDO,
SDI: machine.NINA_SDI,
SCK: machine.NINA_SCK,
})
adaptor = wifinina.New(spi,
machine.NINA_CS,
machine.NINA_ACK,
machine.NINA_GPIO0,
machine.NINA_RESETN)
adaptor.Configure()
}
func main() {
setup()
waitSerial()
connectToAP()
displayIP()
for {
readConnection()
if time.Now().Sub(lastRequestTime).Milliseconds() >= 10000 {
makeHTTPRequest()
}
}
}
// Wait for user to open serial console
func waitSerial() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
}
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()
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(msg string) {
println(msg, "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
-234
View File
@@ -1,234 +0,0 @@
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 (
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor *wifinina.Device
)
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()
connectToAP()
displayIP()
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)
}
const retriesBeforeFailure = 3
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
var err error
for i := 0; i < retriesBeforeFailure; i++ {
println("Connecting to " + ssid)
err = adaptor.ConnectToAccessPoint(ssid, pass, 10*time.Second)
if err == nil {
println("Connected.")
return
}
}
// error connecting to AP
failMessage(err.Error())
}
func displayIP() {
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message("IP address: " + ip.String())
}
func message(msg string) {
println(msg, "\r")
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+5 -4
View File
@@ -4,7 +4,8 @@ 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.D2
var led = machine.LED
func init() {
// Replace neo in the code below to match the pin
// that you are using if different.
neo = machine.D2
}
+6 -5
View File
@@ -4,8 +4,9 @@ package main
import "machine"
// This is the pin assignment for the Digispark only.
// 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
func init() {
// This is the pin assignment for the Digispark only.
// Replace neo and led in the code below to match the pin
// that you are using if different.
neo = machine.Pin(0)
}
+5 -5
View File
@@ -12,14 +12,15 @@ import (
"tinygo.org/x/drivers/ws2812"
)
var leds [10]color.RGBA
var (
neo machine.Pin
leds [10]color.RGBA
)
func main() {
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
neo.Configure(machine.PinConfig{Mode: machine.PinOutput})
ws := ws2812.New(neo)
ws := ws2812.NewWS2812(neo)
rg := false
for {
@@ -35,7 +36,6 @@ func main() {
}
ws.WriteColors(leds[:])
led.Set(rg)
time.Sleep(100 * time.Millisecond)
}
}
+6 -5
View File
@@ -1,10 +1,11 @@
//go:build !digispark && !arduino && !qtpy && !m5stamp_c3 && !thingplus_rp2040
//go:build !digispark && !arduino
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.WS2812
var led = machine.LED
func init() {
// Replace neo in the code below to match the pin
// that you are using if different.
neo = machine.WS2812
}
-10
View File
@@ -1,10 +0,0 @@
//go:build qtpy || m5stamp_c3
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.WS2812
var led = machine.NoPin
-12
View File
@@ -1,12 +0,0 @@
//go:build thingplus_rp2040
package main
import "machine"
// This is the pin assignment for the internal neopixel of the
// Sparkfun thingplus rp2040.
// Replace neo and led in the code below to match the pin
// that you are using if different.
var neo machine.Pin = machine.GPIO8
var led = machine.LED
+2 -1
View File
@@ -80,7 +80,8 @@ func (d *Device) Read() []byte {
func (d *Device) ReadTouchPoint() touch.Point {
d.Read()
z := 0xFFFFF
if d.buf[0] == 0 {
switch d.buf[0] {
case 0, 255:
z = 0
}
+3 -1
View File
@@ -2,10 +2,13 @@ module tinygo.org/x/drivers
go 1.18
replace tinygo.org/x/drivers/mcp9808 => /home/kasterby/Documents/drivers/mcp9808
require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/frankban/quicktest v1.10.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/soypat/natiu-mqtt v0.5.1
golang.org/x/net v0.7.0
tinygo.org/x/tinyfont v0.3.0
tinygo.org/x/tinyterm v0.1.0
@@ -15,6 +18,5 @@ require (
github.com/google/go-cmp v0.5.2 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/kr/text v0.1.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
)
+2 -2
View File
@@ -12,11 +12,11 @@ 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/soypat/natiu-mqtt v0.5.1 h1:rwaDmlvjzD2+3MCOjMZc4QEkDkNwDzbct2TJbpz+TPc=
github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4=
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
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=
+15
View File
@@ -7,6 +7,7 @@ import (
"time"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/pixel"
)
type Config struct {
@@ -31,6 +32,9 @@ type Device struct {
rd machine.Pin
}
// Image buffer type used in the ili9341.
type Image = pixel.Image[pixel.RGB565BE]
var cmdBuf [6]byte
var initCmd = []byte{
@@ -173,6 +177,8 @@ func (d *Device) EnableTEOutput(on bool) {
}
// DrawRGBBitmap copies an RGB bitmap to the internal buffer at given coordinates
//
// Deprecated: use DrawBitmap instead.
func (d *Device) DrawRGBBitmap(x, y int16, data []uint16, w, h int16) error {
k, i := d.Size()
if x < 0 || y < 0 || w <= 0 || h <= 0 ||
@@ -187,6 +193,8 @@ func (d *Device) DrawRGBBitmap(x, y int16, data []uint16, w, h int16) error {
}
// DrawRGBBitmap8 copies an RGB bitmap to the internal buffer at given coordinates
//
// Deprecated: use DrawBitmap instead.
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 ||
@@ -200,6 +208,13 @@ func (d *Device) DrawRGBBitmap8(x, y int16, data []uint8, w, h int16) error {
return nil
}
// DrawBitmap copies the bitmap to the internal buffer on the screen at the
// given coordinates. It returns once the image data has been sent completely.
func (d *Device) DrawBitmap(x, y int16, bitmap Image) error {
width, height := bitmap.Size()
return d.DrawRGBBitmap8(x, y, bitmap.RawBuffer(), int16(width), int16(height))
}
// 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()

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