-
Notifications
You must be signed in to change notification settings - Fork 0
/
controller.go
98 lines (87 loc) · 2.7 KB
/
controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package main
import (
"time"
)
//Controller tracks a number of channels used for manipulating the
//sequencer state.
type Controller struct {
//Used to add sequences to the sequencer
sequenceChannel chan Sequence
//Used to start and stop the controller's master clock
controlChannel chan string
//Provides control (start, stop, destroy) over individual sequences
sequenceControlChannel chan SequenceControl
}
//Encapsulates necessary information for individual sequence control messages.
//Message should be one of "start", "stop" or "destroy"
type SequenceControl struct {
SequenceId string
Message string
}
//Used only within Controllers for tracking an individual sequences channels.
type sequenceChannels struct {
clockChan chan int
controlChan chan string
}
//Uses the controller's sequence channel to add a new sequence.
func (con Controller) Add(seq Sequence) {
con.sequenceChannel <- seq
}
//Uses the controller's sequence control channel to pass control
//messages to individual Sequences.
func (con Controller) SeqCon(seqId string, msg string) {
con.sequenceControlChannel <- SequenceControl{seqId, msg}
}
//Simplifies construction of a new Controller, will start the main
//control function as a go routine.
func NewController(pulsesPerCycle int, stepLen int) Controller {
seqChan := make(chan Sequence)
conChan := make(chan string)
seqConChan := make(chan SequenceControl)
ret := Controller{seqChan, conChan, seqConChan}
go ret.controller(pulsesPerCycle, stepLen, make(map[string]sequenceChannels))
return ret
}
//Runs the master control loop.
func (con *Controller) controller(stepLimit int, stepLen int, controls map[string]sequenceChannels) {
running := false
tickChan := time.Tick((time.Duration)(stepLen) * time.Millisecond)
step := 0
for true {
select {
case <-tickChan:
if running {
for _, con := range controls {
con.clockChan <- step
}
if step += 1; step >= stepLimit {
step = 0
}
}
case newSeq := <-con.sequenceChannel:
clock, control := make(chan int), make(chan string)
//need to stop and remove the old version of an extant sequence:
if oldSeq, exists := controls[newSeq.Id]; exists {
oldSeq.controlChan <- SEQ_DESTROY
delete(controls, newSeq.Id)
}
go newSeq.Stepper(clock, control)
controls[newSeq.Id] = sequenceChannels{clock, control}
case command := <-con.controlChannel:
switch command {
case "start":
running = true
case "stop":
running = false
step = 0
case "reset":
step = 0
}
case seqCommand := <-con.sequenceControlChannel:
controls[seqCommand.SequenceId].controlChan <- seqCommand.Message
if seqCommand.Message == SEQ_DESTROY {
delete(controls, seqCommand.SequenceId)
}
}
}
}