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 } 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.GP21 partybutton := machine.GP20 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) { brightnesschan <- 0 for { <-pushchan brightnesschan <- 255 <-pushchan brightnesschan <- 120 <-pushchan brightnesschan <- 30 <-pushchan brightnesschan <- 0 } } 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) }