cabin-lights/main.go
Drew Bowering 4a29e0c600
swap inside brightness and party buttons
- The outside button is next to the outside light, but not the inside button. This moves it beside the light and puts the party button in the middle (on the prototype board)
2024-04-03 00:56:44 -06:00

288 lines
5.3 KiB
Go

package main
import (
"machine"
"time"
)
type pwm interface {
Top() uint32
Set(uint8, uint32)
Channel(machine.Pin) (uint8, error)
}
type led struct {
pin machine.Pin
pwm pwm
channel uint8
}
func (l *led) InitPWM() error {
var err error
l.channel, err = l.pwm.Channel(l.pin)
return err
}
func (l *led) set(brightness uint32) {
l.pwm.Set(l.channel, (l.pwm.Top()/brightnesspeak)*brightness)
}
type lighthardware struct {
red led
green led
blue led
}
func (lhw *lighthardware) InitPWM() error {
var err error
err = lhw.red.InitPWM()
if err != nil {
return err
}
err = lhw.green.InitPWM()
if err != nil {
return err
}
err = lhw.blue.InitPWM()
if err != nil {
return err
}
return nil
}
type lightSet struct {
inside *lighthardware
inside2 *lighthardware
outside *lighthardware
}
type brightnesses struct {
inside uint32
outside uint32
}
var (
brightnessSteps = []uint32{0, 255, 100, 20}
)
const (
period = uint64(1e9 / 500)
pressdelay = time.Millisecond * 500
brightnesspeak = uint32(255)
)
func main() {
errs := make(chan error)
outsidepushed_raw := make(chan bool)
insidepushed_raw := make(chan bool)
partypushed_raw := make(chan bool)
outsidepushed := make(chan bool)
insidepushed := make(chan bool)
partypushed := make(chan bool)
outsidebrightness := make(chan uint32, 2)
insidebrightness := make(chan uint32, 2)
outsidebutton := machine.GP22
insidebutton := machine.GP20
partybutton := machine.GP21
outsidebutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
insidebutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
partybutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
outsidebutton.SetInterrupt(machine.PinFalling, func(p machine.Pin) {
select {
case outsidepushed_raw <- true:
default:
}
})
insidebutton.SetInterrupt(machine.PinFalling, func(p machine.Pin) {
select {
case insidepushed_raw <- true:
default:
}
})
partybutton.SetInterrupt(machine.PinFalling, func(p machine.Pin) {
select {
case partypushed_raw <- true:
default:
}
})
go delayChan(outsidepushed_raw, outsidepushed)
go delayChan(insidepushed_raw, insidepushed)
go delayChan(partypushed_raw, partypushed)
pwm2 := machine.PWM2
pwm2.Configure(machine.PWMConfig{
Period: period,
})
pwm3 := machine.PWM3
pwm3.Configure(machine.PWMConfig{
Period: period,
})
pwm4 := machine.PWM4
pwm4.Configure(machine.PWMConfig{
Period: period,
})
pwm5 := machine.PWM5
pwm5.Configure(machine.PWMConfig{
Period: period,
})
pwm6 := machine.PWM6
pwm6.Configure(machine.PWMConfig{
Period: period,
})
insideLight := lighthardware{
red: led{
pin: machine.GP11,
pwm: pwm5,
},
green: led{
pin: machine.GP13,
pwm: pwm6,
},
blue: led{
pin: machine.GP12,
pwm: pwm6,
},
}
err := insideLight.InitPWM()
if err != nil {
errs <- err
} else {
insideLight2 := lighthardware{
red: led{
pin: machine.GP8,
pwm: pwm4,
},
green: led{
pin: machine.GP10,
pwm: pwm5,
},
blue: led{
pin: machine.GP9,
pwm: pwm4,
},
}
err = insideLight2.InitPWM()
if err != nil {
errs <- err
} else {
outsideLight := lighthardware{
red: led{
pin: machine.GP5,
pwm: pwm2,
},
green: led{
pin: machine.GP7,
pwm: pwm3,
},
blue: led{
pin: machine.GP6,
pwm: pwm3,
},
}
err = outsideLight.InitPWM()
if err != nil {
errs <- err
} else {
lights := lightSet{
inside: &insideLight,
inside2: &insideLight2,
outside: &outsideLight,
}
go cycleBrightness(insidepushed, insidebrightness)
go cycleBrightness(outsidepushed, outsidebrightness)
go loop(lights, insidebrightness, outsidebrightness, partypushed)
}
}
}
println((<-errs).Error())
}
func delayChan(inchan <-chan bool, outchan chan<- bool) {
var last time.Time
for {
val := <-inchan
now := time.Now()
if now.Sub(last) > pressdelay {
last = now
select {
case outchan <- val:
default:
}
}
}
}
func cycleBrightness(pushchan <-chan bool, brightnesschan chan<- uint32) {
for {
for _, b := range brightnessSteps {
brightnesschan <- b
<-pushchan
}
}
}
func loop(lights lightSet, insidebrightness chan uint32, outsidebrightness chan uint32, partypushed <-chan bool) {
partyChange := make(chan bool)
lastBrightness := make(chan brightnesses)
for {
go normal(lights, insidebrightness, outsidebrightness, partyChange, lastBrightness)
<-partypushed
// go party(lights)
// <-partypushed
partyChange <- true
lb := <-lastBrightness
select {
case insidebrightness <- lb.inside:
default:
}
select {
case outsidebrightness <- lb.outside:
default:
}
}
}
func normal(lights lightSet, inBrightChange <-chan uint32, outBrightChange <-chan uint32, partyChange <-chan bool, lastBrightness chan<- brightnesses) {
var brightIn uint32
var brightOut uint32
for {
select {
case brightIn = <-inBrightChange:
setNormal(lights.inside, brightIn)
setNormal(lights.inside2, brightIn)
case brightOut = <-outBrightChange:
setNormal(lights.outside, brightOut)
case <-partyChange:
lastBrightness <- brightnesses{inside: brightIn, outside: brightOut}
return
}
}
}
func setNormal(light *lighthardware, brightness uint32) {
light.red.set(brightness)
light.green.set(brightness)
light.blue.set(brightness)
}