2020-05-16 09:18:07 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-05-16 18:31:25 +00:00
|
|
|
"fmt"
|
2020-05-16 09:18:07 +00:00
|
|
|
"log"
|
|
|
|
"time"
|
2020-05-16 18:31:25 +00:00
|
|
|
|
|
|
|
webserver "git.martyn.berlin/martyn/LEDController/internal/webserver"
|
|
|
|
queue "git.martyn.berlin/martyn/LEDController/internal/queue"
|
|
|
|
remapping "git.martyn.berlin/martyn/LEDController/internal/remapping"
|
|
|
|
patterns "git.martyn.berlin/martyn/LEDController/internal/patterns"
|
2020-05-16 09:18:07 +00:00
|
|
|
|
|
|
|
"github.com/Hundemeier/go-sacn/sacn"
|
|
|
|
)
|
|
|
|
|
2020-05-16 18:31:25 +00:00
|
|
|
type RGBcolor = [3]byte
|
2020-05-16 09:18:07 +00:00
|
|
|
|
2020-05-16 18:31:25 +00:00
|
|
|
var currentFrame [2][512]byte
|
|
|
|
var channels [2]chan<-[512]byte
|
|
|
|
var sema = make(chan struct{}, 1) // a binary semaphore guarding currentFrame
|
2020-05-16 09:18:07 +00:00
|
|
|
|
2020-05-16 18:31:25 +00:00
|
|
|
var currentEffect queue.QueueItem;
|
|
|
|
var globalEffectChannel = make(chan queue.QueueItem, 1024)
|
2020-05-16 09:18:07 +00:00
|
|
|
|
2020-05-16 18:31:25 +00:00
|
|
|
func foreverLoop() {
|
|
|
|
for /*ever*/ {
|
|
|
|
time.Sleep(40 * time.Millisecond) //25fps
|
|
|
|
for u := 0; u < 2; u++ {
|
|
|
|
sema <- struct{}{} // acquire token
|
|
|
|
channels[u] <- currentFrame[u]
|
|
|
|
<- sema
|
2020-05-16 09:18:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2020-05-16 18:31:25 +00:00
|
|
|
go func() {
|
|
|
|
fmt.Printf("Starting webserver on port %s\n", "5353")
|
|
|
|
webserver.HandleHTTP(globalEffectChannel)
|
|
|
|
}()
|
2020-05-16 09:18:07 +00:00
|
|
|
//instead of "" you could provide an ip-address that the socket should bind to
|
2020-05-16 18:31:25 +00:00
|
|
|
trans, err := sacn.NewTransmitter("", [16]byte{1, 2}, "test")
|
2020-05-16 09:18:07 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-05-16 18:31:25 +00:00
|
|
|
//activates the universes
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
channels[i], err = trans.Activate(uint16(i+1))
|
|
|
|
//deactivate the channel on exit
|
|
|
|
defer close(channels[i])
|
|
|
|
trans.SetMulticast(uint16(i+1), false) //this specific setup will not multicast on windows,
|
|
|
|
trans.SetDestinations(uint16(i+1), []string{"192.168.1.139"})
|
2020-05-16 09:18:07 +00:00
|
|
|
}
|
2020-05-16 18:31:25 +00:00
|
|
|
|
|
|
|
// Plasma for start frame
|
|
|
|
rearranged := remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.PlasmaPanel(68, 4, 40)))
|
|
|
|
currentFrame[0] = remapping.Slice512(rearranged[0])
|
|
|
|
currentFrame[1] = remapping.Slice512(rearranged[1])
|
|
|
|
var e queue.QueueItem
|
|
|
|
e.Effect = "red"
|
|
|
|
e.Duration = 40 * 50
|
|
|
|
globalEffectChannel <- e
|
|
|
|
e.Effect = "plasma"
|
|
|
|
e.Duration = 0
|
|
|
|
e.Speed = 40
|
|
|
|
globalEffectChannel <- e
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for /*ever*/ {
|
|
|
|
if currentEffect.Duration > 0 {
|
|
|
|
currentEffect.Duration -= 40
|
|
|
|
} else {
|
|
|
|
if len(globalEffectChannel) > 0 {
|
|
|
|
currentEffect = <- globalEffectChannel
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var rearranged [][]byte
|
|
|
|
switch currentEffect.Effect {
|
|
|
|
case "line":
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.ZigZag(68, 4)))
|
|
|
|
case "plasma":
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.PlasmaPanel(68, 4, currentEffect.Speed)))
|
|
|
|
case "red":
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, false, remapping.XYGridToLinear(68, 4, patterns.RedPanel(68,4)))
|
|
|
|
case "random":
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, false, remapping.XYGridToLinear(68, 4, patterns.RandomColourPanel(68,4,currentEffect.Speed)))
|
|
|
|
case "linearplasma":
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, false, patterns.LinearPlasma(68*4))
|
|
|
|
case "gradientred":
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, false, patterns.Gradient(255, 0, 0, 0, 0, 255, 0, 68*4))
|
|
|
|
case "sine":
|
|
|
|
var black patterns.RGBcolor
|
|
|
|
var red patterns.RGBcolor
|
|
|
|
red[0] = 255
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.Sinewave(68, 4, black, red, currentEffect.Speed)))
|
|
|
|
case "sinechase":
|
|
|
|
var black patterns.RGBcolor
|
|
|
|
var red patterns.RGBcolor
|
|
|
|
red[0] = 255
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.SineChase(68, 4, black, red, currentEffect.Speed)))
|
|
|
|
default:
|
|
|
|
rearranged = remapping.SliceRearrange(68, 4, false, remapping.XYGridToLinear(68, 4, patterns.FillPanel(68,4, 128,0,128)))
|
|
|
|
}
|
|
|
|
//rearranged := remapping.SliceRearrange(68,4,true,linearPlasma(68*4))
|
|
|
|
sema <- struct{}{} // acquire token
|
|
|
|
currentFrame[0] = remapping.Slice512(rearranged[0])
|
|
|
|
currentFrame[1] = remapping.Slice512(rearranged[1])
|
|
|
|
<- sema
|
|
|
|
time.Sleep(40 * time.Millisecond)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
foreverLoop();
|
|
|
|
}
|