mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-12 10:53:43 +00:00
ft6336: add support for ft6336
This commit is contained in:
@@ -219,12 +219,17 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
|
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
|
||||||
@md5sum ./build/test.uf2
|
@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 */)
|
DRIVERS = $(wildcard */)
|
||||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||||
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
|
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 \
|
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))
|
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
||||||
|
|
||||||
unit-test:
|
unit-test:
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func main() {
|
|||||||
|
|
||||||
## Currently supported devices
|
## Currently supported devices
|
||||||
|
|
||||||
The following 77 devices are supported.
|
The following 78 devices are supported.
|
||||||
|
|
||||||
| Device Name | Interface Type |
|
| 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 |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [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