Last active
July 7, 2021 09:08
-
-
Save tzechienchu/3685e7a2b6680b86f11eaaa4bc03e98c to your computer and use it in GitHub Desktop.
Wio Terminal Goroutine on Button/Timer/Lite ADC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"image/color" | |
"machine" | |
"sync" | |
"time" | |
"tinygo.org/x/drivers/ili9341" | |
) | |
var ( | |
led = machine.LED | |
led1 = machine.BCM27 | |
btnA = machine.WIO_KEY_A | |
btnB = machine.WIO_KEY_B | |
btnC = machine.WIO_KEY_C | |
display *ili9341.Device | |
) | |
var ( | |
black = color.RGBA{0, 0, 0, 255} | |
gray = color.RGBA{32, 32, 32, 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} | |
) | |
func initialize() error { | |
machine.SPI3.Configure(machine.SPIConfig{ | |
SCK: machine.LCD_SCK_PIN, | |
SDO: machine.LCD_SDO_PIN, | |
SDI: machine.LCD_SDI_PIN, | |
Frequency: 48000000, | |
}) | |
backlight := machine.LCD_BACKLIGHT | |
backlight.Configure(machine.PinConfig{Mode: machine.PinOutput}) | |
display = ili9341.NewSPI( | |
machine.SPI3, | |
machine.LCD_DC, | |
machine.LCD_SS_PIN, | |
machine.LCD_RESET, | |
) | |
display.Configure(ili9341.Config{ | |
Rotation: ili9341.Rotation270, | |
}) | |
display.FillScreen(black) | |
backlight.High() | |
return nil | |
} | |
func errDisp(err error) { | |
for { | |
fmt.Printf("%s\r\n", err.Error()) | |
time.Sleep(10 * time.Second) | |
} | |
} | |
func main() { | |
err := initialize() | |
if err != nil { | |
errDisp(err) | |
} | |
label1 := NewLabel(240, 0x12) | |
label2 := NewLabel(240, 0x12) | |
label3A := NewLabel(150, 0x12) | |
label3B := NewLabel(70, 0x12) | |
label3C := NewLabel(70, 0x12) | |
label4 := NewLabel(240, 0x12) | |
done := make(chan interface{}) | |
defer close(done) | |
led.Configure(machine.PinConfig{Mode: machine.PinOutput}) | |
btnA.Configure(machine.PinConfig{Mode: machine.PinInput}) | |
btnB.Configure(machine.PinConfig{Mode: machine.PinInput}) | |
btnC.Configure(machine.PinConfig{Mode: machine.PinInput}) | |
chBtnA := pinDebounce(done, btnA, time.Duration(10)) | |
chBtnB := pinDebounce(done, btnB, time.Duration(10)) | |
chBtnC := pinDebounce(done, btnC, time.Duration(10)) | |
chSLiteRaw := readLightSensor(done, time.Duration(100)) | |
chSLite := lowPass(done, chSLiteRaw) | |
chans := fork2(done, chSLite) | |
chBuffer := buffer(done, 32, chans[1]) | |
chCnt1 := timerFunc(done, time.Duration(100)) | |
chanCnt1s := fork2(done, chCnt1) | |
chGroup15 := group(done, 10, chanCnt1s[0]) | |
chCnt2 := timerFunc(done, time.Duration(500)) | |
chanCnt2s := fork2(done, chCnt2) | |
chGroup22 := group(done, 2, chanCnt2s[0]) | |
chMG12 := merge(done, chGroup15, chGroup22) | |
//time.Sleep(2000 * time.Millisecond) | |
for { | |
select { | |
case cnt := <-chanCnt1s[1]: | |
label1.SetText(fmt.Sprintf("timer-100ms: %04X", cnt), white) | |
display.DrawRGBBitmap(0, 30, label1.buf, label1.w, label1.h) | |
case cnt := <-chanCnt2s[1]: | |
label2.SetText(fmt.Sprintf("timer-500ms: %04X", cnt), white) | |
display.DrawRGBBitmap(0, 50, label2.buf, label2.w, label2.h) | |
case cnt := <-chMG12: | |
fmt.Printf("BufMG...: %v \r\n", cnt[0][0]) | |
//case cnt := <-chGroup22: | |
// fmt.Printf("Buf22...: %v \r\n", cnt) | |
// case cnt := <-chGroup15: | |
// fmt.Printf("Buf15...: %v \r\n", cnt) | |
case btnAV := <-chBtnC: | |
label3A.SetText(fmt.Sprintf("button: %v", btnAV), white) | |
display.DrawRGBBitmap(0, 70, label3A.buf, label3A.w, label3A.h) | |
case btnBV := <-chBtnB: | |
label3B.SetText(fmt.Sprintf("%v", btnBV), white) | |
display.DrawRGBBitmap(150, 70, label3B.buf, label3B.w, label3B.h) | |
case btnCV := <-chBtnA: | |
label3C.SetText(fmt.Sprintf("%v", btnCV), white) | |
display.DrawRGBBitmap(220, 70, label3C.buf, label3C.w, label3C.h) | |
case senLite := <-chans[0]: | |
label4.SetText(fmt.Sprintf("LiteSensor: %v", senLite), white) | |
display.DrawRGBBitmap(0, 90, label4.buf, label4.w, label4.h) | |
case bufferLite := <-chBuffer: | |
//fmt.Printf("Buf...: %v,%v \r\n", bufferLite[0], bufferLite[1]) | |
display.FillRectangle(0, 120, 320, 120, black) | |
for i, v := range bufferLite { | |
display.SetPixel(int16(i)*10, 120+int16(v/40), blue) | |
} | |
} | |
time.Sleep(1 * time.Millisecond) | |
} | |
} | |
func timerFunc( | |
done <-chan interface{}, | |
delay time.Duration, | |
) <-chan uint16 { | |
tStream := make(chan uint16) | |
cnt := uint16(0) | |
go func() { | |
defer close(tStream) | |
for { | |
cnt += 1 | |
select { | |
case <-done: | |
return | |
case tStream <- cnt: | |
} | |
time.Sleep(delay * time.Millisecond) | |
} | |
}() | |
return tStream | |
} | |
func group( | |
done <-chan interface{}, | |
bsize int, | |
vStream <-chan uint16, | |
) <-chan []uint16 { | |
gStream := make(chan []uint16) | |
go func() { | |
defer close(gStream) | |
buffer := make([]uint16, 0) | |
for v := range vStream { | |
select { | |
case <-done: | |
return | |
default: | |
{ | |
buffer = append(buffer, v) | |
if len(buffer) == bsize { | |
gStream <- buffer | |
buffer = make([]uint16, 0) | |
} | |
} | |
} | |
} | |
}() | |
return gStream | |
} | |
func merge( | |
done <-chan interface{}, | |
ch1 <-chan []uint16, | |
ch2 <-chan []uint16, | |
) <-chan [][]uint16 { | |
out := make(chan [][]uint16) | |
go func() { | |
defer close(out) | |
d := make([][]uint16, 0) | |
for { | |
select { | |
case <-done: | |
return | |
case m := <-ch1: | |
d = append(d, m) | |
if len(d) == 2 { | |
out <- d | |
d = make([][]uint16, 0) | |
} | |
case m := <-ch2: | |
d = append(d, m) | |
if len(d) == 2 { | |
out <- d | |
d = make([][]uint16, 0) | |
} | |
default: | |
} | |
time.Sleep(20 * time.Millisecond) | |
} | |
}() | |
return out | |
} | |
func mergeWait(cs ...<-chan []uint16) <-chan []uint16 { | |
out := make(chan []uint16) | |
var wg sync.WaitGroup | |
wg.Add(len(cs)) | |
for _, c := range cs { | |
go func(c <-chan []uint16) { | |
for v := range c { | |
out <- v | |
} | |
wg.Done() | |
}(c) | |
} | |
go func() { | |
wg.Wait() | |
close(out) | |
}() | |
return out | |
} | |
func pinDebounce( | |
done <-chan interface{}, | |
pin machine.Pin, | |
delay time.Duration, | |
) <-chan bool { | |
pStream := make(chan bool) | |
btnV := [2]bool{false, false} | |
go func() { | |
defer close(pStream) | |
for { | |
v1 := !pin.Get() | |
btnV[0] = v1 | |
select { | |
case <-done: | |
return | |
case pStream <- btnV[0] && btnV[1]: | |
} | |
time.Sleep(time.Duration(delay) * time.Millisecond) | |
btnV[1] = btnV[0] | |
} | |
}() | |
return pStream | |
} | |
func readLightSensor( | |
done <-chan interface{}, | |
delay time.Duration, | |
) <-chan uint16 { | |
sensor := machine.ADC{Pin: machine.WIO_LIGHT} | |
sensor.Configure(machine.ADCConfig{}) | |
pStream := make(chan uint16) | |
go func() { | |
defer close(pStream) | |
for { | |
val := sensor.Get() | |
select { | |
case <-done: | |
return | |
case pStream <- val: | |
} | |
time.Sleep(time.Duration(delay) * time.Millisecond) | |
} | |
}() | |
return pStream | |
} | |
func lowPass( | |
done <-chan interface{}, | |
vStream <-chan uint16, | |
) <-chan uint16 { | |
iStream := make(chan uint16) | |
his := uint16(0) | |
fir := func(val uint16) uint16 { | |
his = (his * 6 / 10) + (val * 4 / 10) | |
return his | |
} | |
go func() { | |
defer close(iStream) | |
for v := range vStream { | |
select { | |
case <-done: | |
return | |
case iStream <- fir(v): | |
} | |
} | |
}() | |
return iStream | |
} | |
func fork2( | |
done <-chan interface{}, | |
vStream <-chan uint16, | |
) [2]chan uint16 { | |
var chans [2]chan uint16 | |
for i := range chans { | |
chans[i] = make(chan uint16) | |
} | |
closeChans := func(chans [2]chan uint16) { | |
for i := range chans { | |
close(chans[i]) | |
} | |
} | |
go func() { | |
defer closeChans(chans) | |
for v := range vStream { | |
select { | |
case <-done: | |
return | |
default: | |
{ | |
for i := range chans { | |
chans[i] <- v | |
} | |
} | |
} | |
} | |
}() | |
return chans | |
} | |
func buffer( | |
done <-chan interface{}, | |
bsize int, | |
vStream <-chan uint16, | |
) <-chan []uint16 { | |
buffer := make([]uint16, bsize) | |
addBuffer := func(d uint16) []uint16 { | |
buffer = buffer[1:] | |
buffer = append(buffer, d) | |
return buffer | |
} | |
bStream := make(chan []uint16) | |
go func() { | |
defer close(bStream) | |
for v := range vStream { | |
select { | |
case <-done: | |
return | |
case bStream <- addBuffer(v): | |
} | |
} | |
}() | |
return bStream | |
} | |
// func pinInterruptChan(pin machine.Pin) <-chan bool { | |
// var state volatile.Register8 | |
// ch := make(chan bool) | |
// pin.SetInterrupt(machine.PinToggle, func(p machine.Pin) { | |
// b := false | |
// if state.Get() != 1 { | |
// state.Set(1) | |
// b = true | |
// } else { | |
// state.Set(0) | |
// } | |
// select { | |
// case ch <- b: | |
// default: | |
// } | |
// }) | |
// return ch | |
// } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add