mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
ft6336: add support for ft6336
This commit is contained in:
@@ -219,12 +219,17 @@ endif
|
||||
@md5sum ./build/test.hex
|
||||
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
|
||||
@md5sum ./build/test.uf2
|
||||
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/basic/
|
||||
@md5sum ./build/test.elf
|
||||
tinygo build -size short -o ./build/test.elf -target=m5stack-core2 ./examples/ft6336/touchpaint/
|
||||
@md5sum ./build/test.elf
|
||||
|
||||
DRIVERS = $(wildcard */)
|
||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
|
||||
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \
|
||||
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192 xpt2046
|
||||
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192 xpt2046 \
|
||||
ft6336
|
||||
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
||||
|
||||
unit-test:
|
||||
|
||||
@@ -52,7 +52,7 @@ func main() {
|
||||
|
||||
## Currently supported devices
|
||||
|
||||
The following 77 devices are supported.
|
||||
The following 78 devices are supported.
|
||||
|
||||
| Device Name | Interface Type |
|
||||
|----------|-------------|
|
||||
@@ -78,6 +78,7 @@ The following 77 devices are supported.
|
||||
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
|
||||
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
|
||||
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
|
||||
| [FT6336 touch controller](https://focuslcds.com/content/FT6236.pdf) | I2C |
|
||||
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
|
||||
| [HC-SR04 Ultrasonic distance sensor](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf) | GPIO |
|
||||
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//go:build m5stack_core2
|
||||
// +build m5stack_core2
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"tinygo.org/x/drivers/ft6336"
|
||||
"tinygo.org/x/drivers/i2csoft"
|
||||
"tinygo.org/x/drivers/touch"
|
||||
)
|
||||
|
||||
// InitDisplay initializes the display of each board.
|
||||
func initDevices() (touch.Pointer, error) {
|
||||
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
|
||||
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
|
||||
|
||||
resistiveTouch := ft6336.New(i2c, machine.Pin(39))
|
||||
resistiveTouch.Configure(ft6336.Config{})
|
||||
resistiveTouch.SetPeriodActive(0x00)
|
||||
|
||||
return resistiveTouch, nil
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
touchScreen, _ := initDevices()
|
||||
|
||||
for {
|
||||
touch := touchScreen.ReadTouchPoint()
|
||||
if touch.Z > 0 {
|
||||
//X and Y are 16 bit with 12 bit resolution and need to be scaled for the display size
|
||||
//Z is 24 bit and is typically > 2000 for a touch
|
||||
println("touch:", touch.X, touch.Y, touch.Z)
|
||||
//Example of scaling for m5stack-core2's 320x240 display with 320x270 touch area
|
||||
println("screen:", (touch.X*320)>>16, (touch.Y*270)>>16)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
//go:build m5stack_core2
|
||||
// +build m5stack_core2
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"machine"
|
||||
|
||||
axp192 "tinygo.org/x/drivers/axp192/m5stack-core2-axp192"
|
||||
"tinygo.org/x/drivers/ft6336"
|
||||
"tinygo.org/x/drivers/i2csoft"
|
||||
"tinygo.org/x/drivers/ili9341"
|
||||
"tinygo.org/x/drivers/touch"
|
||||
)
|
||||
|
||||
// InitDisplay initializes the display of each board.
|
||||
func initDevices() (touchPaintDisplay, touch.Pointer, error) {
|
||||
machine.SPI2.Configure(machine.SPIConfig{
|
||||
SCK: machine.LCD_SCK_PIN,
|
||||
SDO: machine.LCD_SDO_PIN,
|
||||
SDI: machine.LCD_SDI_PIN,
|
||||
Frequency: 40e6,
|
||||
})
|
||||
|
||||
i2c := i2csoft.New(machine.SCL0_PIN, machine.SDA0_PIN)
|
||||
i2c.Configure(i2csoft.I2CConfig{Frequency: 100e3})
|
||||
|
||||
axp := axp192.New(i2c)
|
||||
led := axp.LED
|
||||
led.Low()
|
||||
|
||||
display := ili9341.NewSPI(
|
||||
machine.SPI2,
|
||||
machine.LCD_DC_PIN,
|
||||
machine.LCD_SS_PIN,
|
||||
machine.NoPin,
|
||||
)
|
||||
|
||||
// configure display
|
||||
display.Configure(ili9341.Config{
|
||||
Width: 320,
|
||||
Height: 240,
|
||||
DisplayInversion: true,
|
||||
})
|
||||
display.FillScreen(color.RGBA{255, 255, 255, 255})
|
||||
|
||||
display.SetRotation(ili9341.Rotation0Mirror)
|
||||
|
||||
resistiveTouch := ft6336.New(i2c, machine.Pin(39))
|
||||
resistiveTouch.Configure(ft6336.Config{})
|
||||
resistiveTouch.SetPeriodActive(0x00)
|
||||
|
||||
return display, resistiveTouch, nil
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/touch"
|
||||
)
|
||||
|
||||
type touchPaintDisplay interface {
|
||||
drivers.Displayer
|
||||
FillRectangle(x, y, width, height int16, c color.RGBA) error
|
||||
DrawRectangle(x, y, w, h int16, c color.RGBA) error
|
||||
}
|
||||
|
||||
var (
|
||||
white = color.RGBA{255, 255, 255, 255}
|
||||
black = color.RGBA{0, 0, 0, 255}
|
||||
red = color.RGBA{255, 0, 0, 255}
|
||||
green = color.RGBA{0, 255, 0, 255}
|
||||
blue = color.RGBA{0, 0, 255, 255}
|
||||
magenta = color.RGBA{255, 0, 255, 255}
|
||||
yellow = color.RGBA{255, 255, 0, 255}
|
||||
cyan = color.RGBA{0, 255, 255, 255}
|
||||
|
||||
oldColor color.RGBA
|
||||
currentColor color.RGBA
|
||||
)
|
||||
|
||||
const (
|
||||
penRadius = 3
|
||||
boxSize = 30
|
||||
|
||||
Xmin = 0
|
||||
Xmax = 0xFFFF
|
||||
Ymin = 0
|
||||
Ymax = 0xFFFF
|
||||
)
|
||||
|
||||
func main() {
|
||||
display, resistiveTouch, _ := initDevices()
|
||||
|
||||
// fill the background and activate the backlight
|
||||
width, height := display.Size()
|
||||
display.FillRectangle(0, 0, width, height, black)
|
||||
|
||||
// make color selection boxes
|
||||
display.FillRectangle(0, 0, boxSize, boxSize, red)
|
||||
display.FillRectangle(boxSize, 0, boxSize, boxSize, yellow)
|
||||
display.FillRectangle(boxSize*2, 0, boxSize, boxSize, green)
|
||||
display.FillRectangle(boxSize*3, 0, boxSize, boxSize, cyan)
|
||||
display.FillRectangle(boxSize*4, 0, boxSize, boxSize, blue)
|
||||
display.FillRectangle(boxSize*5, 0, boxSize, boxSize, magenta)
|
||||
display.FillRectangle(boxSize*6, 0, boxSize, boxSize, black)
|
||||
display.FillRectangle(boxSize*7, 0, boxSize, boxSize, white)
|
||||
|
||||
// set the initial color to red and draw a box to highlight it
|
||||
oldColor = red
|
||||
currentColor = red
|
||||
display.DrawRectangle(0, 0, boxSize, boxSize, white)
|
||||
|
||||
last := touch.Point{}
|
||||
|
||||
// loop and poll for touches, including performing debouncing
|
||||
debounce := 0
|
||||
for {
|
||||
|
||||
point := resistiveTouch.ReadTouchPoint()
|
||||
touch := touch.Point{}
|
||||
if point.Z>>6 > 100 {
|
||||
rawX := mapval(point.X, Xmin, Xmax, 0, int(width))
|
||||
rawY := mapval(point.Y, Ymin, Ymax, 0, int(height))
|
||||
touch.X = rawX
|
||||
touch.Y = rawY
|
||||
touch.Z = 1
|
||||
} else {
|
||||
touch.X = 0
|
||||
touch.Y = 0
|
||||
touch.Z = 0
|
||||
}
|
||||
|
||||
if last.Z != touch.Z {
|
||||
debounce = 0
|
||||
last = touch
|
||||
} else if math.Abs(float64(touch.X-last.X)) > 4 ||
|
||||
math.Abs(float64(touch.Y-last.Y)) > 4 {
|
||||
debounce = 0
|
||||
last = touch
|
||||
} else if debounce > 1 {
|
||||
debounce = 0
|
||||
HandleTouch(display, last)
|
||||
} else if touch.Z > 0 {
|
||||
debounce++
|
||||
} else {
|
||||
last = touch
|
||||
debounce = 0
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// based on Arduino's "map" function
|
||||
func mapval(x int, inMin int, inMax int, outMin int, outMax int) int {
|
||||
return (x-inMin)*(outMax-outMin)/(inMax-inMin) + outMin
|
||||
}
|
||||
|
||||
func HandleTouch(display touchPaintDisplay, touch touch.Point) {
|
||||
|
||||
if int16(touch.Y) < boxSize {
|
||||
oldColor = currentColor
|
||||
x := int16(touch.X)
|
||||
switch {
|
||||
case x < boxSize:
|
||||
currentColor = red
|
||||
case x < boxSize*2:
|
||||
currentColor = yellow
|
||||
case x < boxSize*3:
|
||||
currentColor = green
|
||||
case x < boxSize*4:
|
||||
currentColor = cyan
|
||||
case x < boxSize*5:
|
||||
currentColor = blue
|
||||
case x < boxSize*6:
|
||||
currentColor = magenta
|
||||
case x < boxSize*7:
|
||||
currentColor = black
|
||||
case x < boxSize*8:
|
||||
currentColor = white
|
||||
}
|
||||
|
||||
if oldColor == currentColor {
|
||||
return
|
||||
}
|
||||
|
||||
display.DrawRectangle((x/boxSize)*boxSize, 0, boxSize, boxSize, white)
|
||||
switch oldColor {
|
||||
case red:
|
||||
x = 0
|
||||
case yellow:
|
||||
x = boxSize
|
||||
case green:
|
||||
x = boxSize * 2
|
||||
case cyan:
|
||||
x = boxSize * 3
|
||||
case blue:
|
||||
x = boxSize * 4
|
||||
case magenta:
|
||||
x = boxSize * 5
|
||||
case black:
|
||||
x = boxSize * 6
|
||||
case white:
|
||||
x = boxSize * 7
|
||||
}
|
||||
display.FillRectangle(int16(x), 0, boxSize, boxSize, oldColor)
|
||||
|
||||
}
|
||||
|
||||
if (int16(touch.Y) - penRadius) > boxSize {
|
||||
display.FillRectangle(
|
||||
int16(touch.X), int16(touch.Y), penRadius*2, penRadius*2, currentColor)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// Package ft6336 provides a driver for the FT6336 I2C Self-Capacitive touch
|
||||
// panel controller.
|
||||
//
|
||||
// Datasheet: https://focuslcds.com/content/FT6236.pdf
|
||||
//
|
||||
package ft6336
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/touch"
|
||||
)
|
||||
|
||||
// Device wraps FT6336 I2C Self-Capacitive touch
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
buf []byte
|
||||
Address uint8
|
||||
intPin machine.Pin
|
||||
}
|
||||
|
||||
// New returns FT6336 device for the provided I2C bus using default address.
|
||||
func New(i2c drivers.I2C, intPin machine.Pin) *Device {
|
||||
return &Device{
|
||||
bus: i2c,
|
||||
buf: make([]byte, 11),
|
||||
Address: Address,
|
||||
intPin: intPin,
|
||||
}
|
||||
}
|
||||
|
||||
// Config contains settings for FT6636.
|
||||
type Config struct {
|
||||
}
|
||||
|
||||
// Configure the FT6336 device.
|
||||
func (d *Device) Configure(config Config) error {
|
||||
d.write1Byte(0xA4, 0x00)
|
||||
d.intPin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetGMode sets interrupt mode.
|
||||
// 0x00 : Interrupt Polling mode
|
||||
// 0x01 : Interrupt Trigger mode (default)
|
||||
func (d *Device) SetGMode(v uint8) {
|
||||
d.write1Byte(RegGMode, v)
|
||||
}
|
||||
|
||||
// GetGMode gets interrupt mode.
|
||||
func (d *Device) GetGMode() uint8 {
|
||||
return d.read8bit(RegGMode)
|
||||
}
|
||||
|
||||
// SetPeriodActive sets report rate in Active mode.
|
||||
func (d *Device) SetPeriodActive(v uint8) {
|
||||
d.write1Byte(RegPeriodActive, v)
|
||||
}
|
||||
|
||||
// GetPeriodActive gets report rate in Active mode.
|
||||
func (d *Device) GetPeriodActive() uint8 {
|
||||
return d.read8bit(RegPeriodActive)
|
||||
}
|
||||
|
||||
// GetFirmwareID gets firmware version.
|
||||
func (d *Device) GetFirmwareID() uint8 {
|
||||
return d.read8bit(RegFirmid)
|
||||
}
|
||||
|
||||
// Read reads the registers.
|
||||
func (d *Device) Read() []byte {
|
||||
d.bus.Tx(uint16(d.Address), []byte{0x02}, d.buf[:])
|
||||
return d.buf[:]
|
||||
}
|
||||
|
||||
// ReadTouchPoint reads a single touch.Point from the device. The maximum value
|
||||
// for each touch.Point is 0xFFFF.
|
||||
func (d *Device) ReadTouchPoint() touch.Point {
|
||||
d.Read()
|
||||
z := 0xFFFFF
|
||||
if d.buf[0] == 0 {
|
||||
z = 0
|
||||
}
|
||||
|
||||
//Scale X&Y to 16 bit for consistency across touch drivers
|
||||
return touch.Point{
|
||||
X: (int(d.buf[1]&0x0F)<<8 + int(d.buf[2])) * ((1 << 16) / 320),
|
||||
Y: (int(d.buf[3]&0x0F)<<8 + int(d.buf[4])) * ((1 << 16) / 270),
|
||||
Z: z,
|
||||
}
|
||||
}
|
||||
|
||||
// Touched returns if touched or not.
|
||||
func (d *Device) Touched() bool {
|
||||
p := d.ReadTouchPoint()
|
||||
return p.Z > 0
|
||||
}
|
||||
|
||||
func (d *Device) write1Byte(reg, data uint8) {
|
||||
d.bus.WriteRegister(d.Address, reg, []byte{data})
|
||||
}
|
||||
|
||||
func (d *Device) read8bit(reg uint8) uint8 {
|
||||
d.bus.ReadRegister(d.Address, reg, d.buf[:1])
|
||||
return d.buf[0]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package ft6336
|
||||
|
||||
// 0x00 DEV_MODE
|
||||
// 0x01 GEST_ID
|
||||
// 0x02 TD_STATUS
|
||||
// 0x03 P1_XH
|
||||
// 0x04 P1_XL
|
||||
// 0x05 P1_YH
|
||||
// 0x06 P1_YL
|
||||
// 0x07 P1_WEIGHT
|
||||
// 0x08 P1_MISC
|
||||
// 0x09 P2_XH
|
||||
// 0x0A P2_XL
|
||||
// 0x0B P2_YH
|
||||
// 0x0C P2_YL
|
||||
// 0x0D P2_WEIGHT
|
||||
// 0x0E P2_MISC
|
||||
// 0x80 TH_GROUP
|
||||
// 0x85 TH_DIFF
|
||||
// 0x86 CTRL
|
||||
// 0x87 TIMEENTERMONITOR
|
||||
// 0x88 PERIODACTIVE
|
||||
// 0x89 PERIODMONITOR
|
||||
// 0x91 RADIAN_VALUE
|
||||
// 0x92 OFFSET_LEFT_RIGHT
|
||||
// 0x93 OFFSET_UP_D
|
||||
// 0x94 DISTANCE_LE
|
||||
// 0x95 DISTANCE_UP
|
||||
// 0x96 DISTANCE_ZO
|
||||
// ...
|
||||
// 0xA1 LIB_VER_H
|
||||
// 0xA2 LIB_VER_L
|
||||
// 0xA3 CIPHER
|
||||
// 0xA4 G_MODE
|
||||
// 0xA5 PWR_MODE
|
||||
// 0xA6 FIRMID
|
||||
// 0xA8 FOCALTECH_ID
|
||||
// ...
|
||||
// 0xAF RELEASE_CODE_ID
|
||||
// ...
|
||||
// 0xBC STATE
|
||||
|
||||
const (
|
||||
Address = 0x38
|
||||
|
||||
RegPeriodActive = 0x88
|
||||
RegGMode = 0xA4
|
||||
RegFirmid = 0xA6
|
||||
)
|
||||
Reference in New Issue
Block a user