Compare commits

..

No commits in common. "master" and "v0.0.5" have entirely different histories.

8 changed files with 30 additions and 314 deletions

View file

@ -1,7 +1,3 @@
# LEDController # LEDController
Testing out sending e1.31 sACM packets to strings of ws2812b Testing out sending e1.31 sACM packets to strings of ws2812b
Seems to be working nicely.
Used for my streaming setup on https://twitch.tv/iMartynOnTwitch

View file

@ -1,5 +1,5 @@
kind: pipeline kind: pipeline
type: kubernetes type: docker
name: linux-amd64-taggedver name: linux-amd64-taggedver
platform: platform:
@ -39,7 +39,7 @@ trigger:
--- ---
kind: pipeline kind: pipeline
type: kubernetes type: docker
name: linux-amd64-devel-master name: linux-amd64-devel-master
platform: platform:

View file

@ -18,8 +18,8 @@ import (
type RGBcolor = [3]byte type RGBcolor = [3]byte
var currentFrame [99][512]byte //TODO make dynamic var currentFrame [2][512]byte
var channels [99]chan<- [512]byte var channels [2]chan<- [512]byte
var sema = make(chan struct{}, 1) // a binary semaphore guarding currentFrame var sema = make(chan struct{}, 1) // a binary semaphore guarding currentFrame
var currentEffect queue.QueueItem var currentEffect queue.QueueItem
@ -30,16 +30,9 @@ var overrideEffect queue.QueueItem
var overrideFlag = make(chan queue.QueueItem, 1) var overrideFlag = make(chan queue.QueueItem, 1)
var previousEffect queue.QueueItem var previousEffect queue.QueueItem
var msDelay = 0
func isColorSet(c RGBcolor) bool {
// Any color so long as it's NOT black!
return c[0] != 0 || c[1] != 0 || c[2] != 0
}
func foreverLoop() { func foreverLoop() {
for /*ever*/ { for /*ever*/ {
time.Sleep(time.Duration(msDelay) * time.Millisecond) //25fps time.Sleep(40 * time.Millisecond) //25fps
for u := 0; u < universeCount; u++ { for u := 0; u < universeCount; u++ {
sema <- struct{}{} // acquire token sema <- struct{}{} // acquire token
channels[u] <- currentFrame[u] channels[u] <- currentFrame[u]
@ -76,15 +69,11 @@ func main() {
PanelWidth, err := strconv.Atoi(os.Getenv("PANEL_WIDTH")) PanelWidth, err := strconv.Atoi(os.Getenv("PANEL_WIDTH"))
if err != nil { if err != nil {
PanelWidth = 60 PanelWidth = 68
} }
PanelHeight, err := strconv.Atoi(os.Getenv("PANEL_HEIGHT")) PanelHeight, err := strconv.Atoi(os.Getenv("PANEL_HEIGHT"))
if err != nil { if err != nil {
PanelHeight = 15 PanelHeight = 4
}
msDelay, err = strconv.Atoi(os.Getenv("MS_DELAY"))
if err != nil {
msDelay = 40
} }
universeCount = int(math.Ceil(float64(PanelHeight*PanelWidth*3) / 510)) universeCount = int(math.Ceil(float64(PanelHeight*PanelWidth*3) / 510))
@ -130,37 +119,26 @@ func main() {
globalEffectChannel <- e globalEffectChannel <- e
e.Effect = "queue" e.Effect = "queue"
overrideEffect = e overrideEffect = e
previousEffect.Effect = "queue"
go func() { go func() {
for /*ever*/ { for /*ever*/ {
if len(overrideFlag) > 0 { if len(overrideFlag) > 0 {
e = <-overrideFlag e = <-overrideFlag
if e.Effect == "queue" { if e.Effect == "queue" {
if previousEffect.Effect != "queue" { fmt.Printf("Returning to queue : %s\n", currentEffect.Effect)
fmt.Printf("Returning to queue : %s\n", previousEffect.Effect)
overrideEffect = e overrideEffect = e
currentEffect = previousEffect currentEffect = previousEffect
previousEffect.Effect = "queue"
currentEffect = <-globalEffectChannel
}
} else { } else {
fmt.Printf("Overriding with : %s\n", e.Effect) fmt.Printf("Overriding with : %s\n", e.Effect)
if previousEffect.Effect == "queue" {
previousEffect = currentEffect previousEffect = currentEffect
}
overrideEffect = e overrideEffect = e
currentEffect = e currentEffect = e
} }
} }
if overrideEffect.Effect == "queue" { if overrideEffect.Effect == "queue" {
if currentEffect.Duration > 0 { if currentEffect.Duration > 0 {
if currentEffect.Duration%uint64(msDelay) != 0 { currentEffect.Duration -= 40
currentEffect.Duration = uint64(currentEffect.Duration/uint64(msDelay)) * uint64(msDelay)
}
currentEffect.Duration -= uint64(msDelay)
} else { } else {
if len(globalEffectChannel) > 0 { if len(globalEffectChannel) > 0 {
previousEffect.Effect = "queue"
lastEffect := currentEffect lastEffect := currentEffect
currentEffect = <-globalEffectChannel currentEffect = <-globalEffectChannel
if lastEffect != currentEffect { if lastEffect != currentEffect {
@ -174,11 +152,7 @@ func main() {
case "line": case "line":
rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, true, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.ZigZag(PanelWidth, PanelHeight))) rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, true, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.ZigZag(PanelWidth, PanelHeight)))
case "plasma": case "plasma":
if isColorSet(currentEffect.SeedColour) {
rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, true, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.PlasmaPanelSingleColor(PanelWidth, PanelHeight, currentEffect.Speed, currentEffect.SeedColour)))
} else {
rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, true, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.PlasmaPanel(PanelWidth, PanelHeight, currentEffect.Speed))) rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, true, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.PlasmaPanel(PanelWidth, PanelHeight, currentEffect.Speed)))
}
case "red": case "red":
rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, false, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.RedPanel(PanelWidth, PanelHeight))) rearranged = remapping.SliceRearrange(PanelWidth, PanelHeight, false, remapping.XYGridToLinear(PanelWidth, PanelHeight, patterns.RedPanel(PanelWidth, PanelHeight)))
case "random": case "random":

View file

@ -1,45 +0,0 @@
package fynewidget
import (
"image/color"
"fyne.io/fyne/widget"
"fyne.io/fyne"
)
// OutputWidget describes a coloured rectangle primitive in a Fyne canvas
type OutputWidget struct {
widget.BaseWidget
CreateRenderer() WidgetRenderer
}
// NewOutputWidget returns a new OutputWidget instance
func NewOutputWidget(color color.Color) *OutputWidget {
return &OutputWidget{}
}
// MinSize of panel
func (l *OutputWidget) MinSize() fyne.Size {
return fyne.NewSize(320, 200)
}
// CreateRenderer gets the widget renderer
func (t *Table) CreateRenderer() fyne.WidgetRenderer {
return widget.new
}
/*
// NewOutputWidget Creates a new widget for outputting the patterns recieved over UDP
func NewOutputWidget() *fyne.Container {
theBox := NewOutputWidget(theme.PrimaryColor())
theBox.Resize(fyne.NewSize(320, 200))
c := fyne.NewContainer(theBox)
c.Resize(fyne.NewSize(320, 200))
return c
}
*/

View file

@ -1,138 +0,0 @@
package patterns
var FontData = [126][]byte{{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00}, // 32 ' '
{0x5f}, // 33 '!'
{0x07, 0x00, 0x07}, // 34 '"'
{0x14, 0x3e, 0x14, 0x3e, 0x14}, // 35 '#'
{0x24, 0x4a, 0xcb, 0x52, 0x24}, // 36 '$'
{0x22, 0x15, 0x2a, 0x54, 0x22}, // 37 '%'
{0x36, 0x49, 0x55, 0x22, 0x50}, // 38 '&'
{0x07}, // 39 '''
{0x1c, 0x22, 0x41}, // 40 '('
{0x41, 0x22, 0x1c}, // 41 ')'
{0x14, 0x08, 0x3e, 0x08, 0x14}, // 42 '*'
{0x08, 0x08, 0x3e, 0x08, 0x08}, // 43 '+'
{0xc0, 0x60}, // 44 ','
{0x08, 0x08, 0x08}, // 45 '-'
{0x60, 0x60}, // 46 '.'
{0x20, 0x10, 0x08, 0x04, 0x02}, // 47 '/'
{0x3e, 0x51, 0x49, 0x45, 0x3e}, // 48 '0'
{0x42, 0x42, 0x7f, 0x40, 0x40}, // 49 '1'
{0x42, 0x61, 0x51, 0x49, 0x46}, // 50 '2'
{0x22, 0x41, 0x49, 0x49, 0x36}, // 51 '3'
{0x18, 0x14, 0x52, 0x7f, 0x50}, // 52 '4'
{0x27, 0x45, 0x45, 0x45, 0x39}, // 53 '5'
{0x3e, 0x45, 0x45, 0x45, 0x38}, // 54 '6'
{0x01, 0x01, 0x71, 0x09, 0x07}, // 55 '7'
{0x36, 0x49, 0x49, 0x49, 0x36}, // 56 '8'
{0x0e, 0x51, 0x51, 0x51, 0x3e}, // 57 '9'
{0x66, 0x66}, // 58 ':'
{0xc6, 0x66}, // 59 ';'
{0x08, 0x14, 0x22, 0x41}, // 60 '<'
{0x14, 0x14, 0x14, 0x14, 0x14}, // 61 '='
{0x41, 0x22, 0x14, 0x08}, // 62 '>'
{0x02, 0x01, 0x51, 0x09, 0x06}, // 63 '?'
{0x3e, 0x41, 0x5d, 0x55, 0x5e}, // 64 '@'
{0x7c, 0x12, 0x11, 0x12, 0x7c}, // 65 'A'
{0x7f, 0x49, 0x49, 0x49, 0x36}, // 66 'B'
{0x3e, 0x41, 0x41, 0x41, 0x22}, // 67 'C'
{0x7f, 0x41, 0x41, 0x41, 0x3e}, // 68 'D'
{0x7f, 0x49, 0x49, 0x49, 0x41}, // 69 'E'
{0x7f, 0x09, 0x09, 0x09, 0x01}, // 70 'F'
{0x3e, 0x41, 0x41, 0x49, 0x3a}, // 71 'G'
{0x7f, 0x08, 0x08, 0x08, 0x7f}, // 72 'H'
{0x41, 0x41, 0x7f, 0x41, 0x41}, // 73 'I'
{0x30, 0x40, 0x40, 0x40, 0x3f}, // 74 'J'
{0x7f, 0x08, 0x14, 0x22, 0x41}, // 75 'K'
{0x7f, 0x40, 0x40, 0x40, 0x40}, // 76 'L'
{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // 77 'M'
{0x7f, 0x02, 0x04, 0x08, 0x7f}, // 78 'N'
{0x3e, 0x41, 0x41, 0x41, 0x3e}, // 79 'O'
{0x7f, 0x09, 0x09, 0x09, 0x06}, // 80 'P'
{0x3e, 0x41, 0x61, 0x41, 0xbe}, // 81 'Q'
{0x7f, 0x09, 0x09, 0x09, 0x76}, // 82 'R'
{0x26, 0x49, 0x49, 0x49, 0x32}, // 83 'S'
{0x01, 0x01, 0x7f, 0x01, 0x01}, // 84 'T'
{0x3f, 0x40, 0x40, 0x40, 0x3f}, // 85 'U'
{0x07, 0x18, 0x60, 0x18, 0x07}, // 86 'V'
{0x7f, 0x20, 0x18, 0x20, 0x7f}, // 87 'W'
{0x63, 0x14, 0x08, 0x14, 0x63}, // 88 'X'
{0x07, 0x08, 0x70, 0x08, 0x07}, // 89 'Y'
{0x61, 0x51, 0x49, 0x45, 0x43}, // 90 'Z'
{0x7f, 0x41}, // 91 '['
{0x02, 0x04, 0x08, 0x10, 0x20}, // 92 '\'
{0x41, 0x7f}, // 93 ']'
{0x04, 0x02, 0x01, 0x02, 0x04}, // 94 '^'
{0x80, 0x80, 0x80, 0x80, 0x80}, // 95 '_'
{0x01, 0x02}, // 96 '`'
{0x20, 0x54, 0x54, 0x78}, // 97 'a'
{0x7f, 0x44, 0x44, 0x38}, // 98 'b'
{0x38, 0x44, 0x44, 0x28}, // 99 'c'
{0x38, 0x44, 0x44, 0x7f}, // 100 'd'
{0x38, 0x54, 0x54, 0x58}, // 101 'e'
{0x08, 0x7e, 0x09, 0x02}, // 102 'f'
{0x18, 0xa4, 0xa4, 0x7c}, // 103 'g'
{0x7f, 0x04, 0x04, 0x78}, // 104 'h'
{0x44, 0x7d, 0x40}, // 105 'i'
{0x84, 0x7d}, // 106 'j'
{0x7f, 0x10, 0x28, 0x44}, // 107 'k'
{0x41, 0x7f, 0x40}, // 108 'l'
{0x7c, 0x04, 0x7c, 0x04, 0x78}, // 109 'm'
{0x7c, 0x08, 0x04, 0x78}, // 110 'n'
{0x38, 0x44, 0x44, 0x38}, // 111 'o'
{0xfc, 0x24, 0x24, 0x18}, // 112 'p'
{0x18, 0x24, 0x24, 0xfc}, // 113 'q'
{0x7c, 0x08, 0x04, 0x08}, // 114 'r'
{0x48, 0x54, 0x54, 0x24}, // 115 's'
{0x04, 0x3f, 0x44}, // 116 't'
{0x3c, 0x40, 0x20, 0x7c}, // 117 'u'
{0x3c, 0x40, 0x3c}, // 118 'v'
{0x3c, 0x40, 0x3c, 0x40, 0x3c}, // 119 'w'
{0x6c, 0x10, 0x6c}, // 120 'x'
{0x1c, 0xa0, 0xa0, 0x7c}, // 121 'y'
{0x64, 0x54, 0x4c}, // 122 'z'
{0x08, 0x36, 0x41}, // 123 '{'
{0x7f}, // 124 '|'
{0x41, 0x36, 0x08}, // 125 '}'
{0x08, 0x04, 0x08, 0x04}} // 126 '~'
func Letter(whichLetter rune) [][]RGBcolor {
w := 8
h := 8
grid := make([][]RGBcolor, w)
for i := 0; i < w; i++ {
grid[i] = make([]RGBcolor, h)
}
//index := int(whichLetter)
return grid
}

View file

@ -112,46 +112,3 @@ func PlasmaPanel(w int, h int, speed uint16) [][]RGBcolor {
} }
return grid return grid
} }
func singleColorPlasmaFromFloatVal(val float64, baseColor RGBcolor) (byte, byte, byte) {
var r byte
var g byte
var b byte
val = positiveModF(val)
r = byte(math.Trunc(float64(baseColor[0]) * val))
g = byte(math.Trunc(float64(baseColor[1]) * val))
b = byte(math.Trunc(float64(baseColor[2]) * val))
return r, g, b
}
func PlasmaPanelSingleColor(w int, h int, speed uint16, baseColor RGBcolor) [][]RGBcolor {
grid := make([][]RGBcolor, w)
for i := 0; i < w; i++ {
grid[i] = make([]RGBcolor, h)
}
palletteOffset -= 0.05 / 1.0
if palletteOffset < 0 {
palletteOffset += 1.0
}
offset := 0.5 // center offset
scaleW := math.Pi * 2.0 / float64(w)
scaleH := math.Pi * 2.0 / float64(h)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
u := math.Cos((float64(x) + offset) * scaleW)
v := math.Cos((float64(y) + offset) * scaleH)
j := math.Cos(offset * scaleW) // 2D - No Z
e := (u + v + j + 3.0) / 6.0
r, g, b := singleColorPlasmaFromFloatVal(palletteOffset+e, baseColor)
var rgb [3]byte
rgb[0] = r
rgb[1] = g
rgb[2] = b
grid[x][y] = rgb
}
}
return grid
}

View file

@ -4,7 +4,7 @@ type RGBcolor = [3]byte
type QueueItem struct { type QueueItem struct {
Effect string Effect string
Duration uint64 Duration uint16
Speed uint16 //only used by some patterns Speed uint16 //only used by some patterns
SeedColour RGBcolor // only used by some patterns SeedColour RGBcolor // only used by some patterns
SecondColour RGBcolor // only used by some patterns SecondColour RGBcolor // only used by some patterns

View file

@ -39,15 +39,11 @@ func PatternHandler(response http.ResponseWriter, request *http.Request) {
e.Effect = strings.ToLower(vars["pattern"]) e.Effect = strings.ToLower(vars["pattern"])
_, found := vars["duration"] _, found := vars["duration"]
if found { if found {
i, _ := strconv.ParseUint(vars["duration"], 10, 64) i, _ := strconv.Atoi(vars["duration"])
e.Duration = i e.Duration = uint16(i)
} else {
if vars["override"] == "true" {
e.Duration = 0
} else { } else {
e.Duration = 5000 e.Duration = 5000
} }
}
_, found = vars["speed"] _, found = vars["speed"]
if found { if found {
i, _ := strconv.Atoi(vars["speed"]) i, _ := strconv.Atoi(vars["speed"])
@ -55,17 +51,6 @@ func PatternHandler(response http.ResponseWriter, request *http.Request) {
} else { } else {
e.Speed = 40 e.Speed = 40
} }
if vars["color"] != "" {
var c queue.RGBcolor
for cn, cv := range colornames.Map {
if cn == strings.ToLower(vars["color"]) {
c[0] = cv.R
c[1] = cv.G
c[2] = cv.B
}
}
e.SeedColour = c
}
if vars["override"] == "true" { if vars["override"] == "true" {
overrideFlag <- e overrideFlag <- e
} else { } else {
@ -82,15 +67,11 @@ func ColourHandler(response http.ResponseWriter, request *http.Request) {
e.Effect = "colour" e.Effect = "colour"
_, found := vars["duration"] _, found := vars["duration"]
if found { if found {
i, _ := strconv.ParseUint(vars["duration"], 10, 64) i, _ := strconv.Atoi(vars["duration"])
e.Duration = i e.Duration = uint16(i)
} else {
if vars["override"] == "true" {
e.Duration = 0
} else { } else {
e.Duration = 5000 e.Duration = 5000
} }
}
var c queue.RGBcolor var c queue.RGBcolor
for cn, cv := range colornames.Map { for cn, cv := range colornames.Map {
if cn == strings.ToLower(vars["name"]) { if cn == strings.ToLower(vars["name"]) {
@ -116,15 +97,11 @@ func FadeHandler(response http.ResponseWriter, request *http.Request) {
e.Effect = "fade" e.Effect = "fade"
_, found := vars["duration"] _, found := vars["duration"]
if found { if found {
i, _ := strconv.ParseUint(vars["duration"], 10, 64) i, _ := strconv.Atoi(vars["duration"])
e.Duration = i e.Duration = uint16(i)
} else {
if vars["override"] == "true" {
e.Duration = 0
} else { } else {
e.Duration = 5000 e.Duration = 5000
} }
}
var c queue.RGBcolor var c queue.RGBcolor
for cn, cv := range colornames.Map { for cn, cv := range colornames.Map {
if cn == strings.ToLower(vars["namefrom"]) { if cn == strings.ToLower(vars["namefrom"]) {
@ -166,14 +143,9 @@ func HandleHTTP(queueChannel chan queue.QueueItem, Port int, overrideChannel cha
r.NotFoundHandler = http.HandlerFunc(NotFoundHandler) r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
r.HandleFunc("/", RootHandler) r.HandleFunc("/", RootHandler)
r.HandleFunc("/healthz", HealthHandler) r.HandleFunc("/healthz", HealthHandler)
r.HandleFunc("/pattern/{pattern}/override={override}", PatternHandler) r.HandleFunc("/pattern/{pattern}", PatternHandler)
r.HandleFunc("/pattern/{pattern}/", PatternHandler)
r.HandleFunc("/pattern/{pattern}/{duration}", PatternHandler) r.HandleFunc("/pattern/{pattern}/{duration}", PatternHandler)
r.HandleFunc("/pattern/{pattern}/{duration}/{speed}", PatternHandler) r.HandleFunc("/pattern/{pattern}/{duration}/{speed}", PatternHandler)
r.HandleFunc("/colorpattern/{color}/{pattern}/override={override}", PatternHandler)
r.HandleFunc("/colorpattern/{color}/{pattern}/", PatternHandler)
r.HandleFunc("/colorpattern/{color}/{pattern}/{duration}", PatternHandler)
r.HandleFunc("/colorpattern/{color}/{pattern}/{duration}/{speed}", PatternHandler)
r.HandleFunc("/colour/{name}", ColourHandler) r.HandleFunc("/colour/{name}", ColourHandler)
r.HandleFunc("/colour/{name}/override={override}", ColourHandler) r.HandleFunc("/colour/{name}/override={override}", ColourHandler)
r.HandleFunc("/colour/{name}/{duration}", ColourHandler) r.HandleFunc("/colour/{name}/{duration}", ColourHandler)