forked from microsoft/microcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtiles.ts
287 lines (255 loc) · 9.21 KB
/
tiles.ts
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
namespace microcode {
type SensorMap = { [id: string]: SensorDefn }
type FilterMap = { [id: string]: FilterDefn }
type ActuatorMap = { [id: string]: ActuatorDefn }
type ModifierMap = { [id: string]: ModifierDefn }
export type TileDefnMap = { [id: string]: TileDefn }
export type TileDatabase = {
[id: string]: TileDefnMap
sensors: SensorMap
filters: FilterMap
actuators: ActuatorMap
modifiers: ModifierMap
}
// Once a tid is assigned, it can NEVER BE CHANGED OR REPURPOSED.
// Every tid must be unique in the set of all tids.
export const TID_SENSOR_ALWAYS = "S1"
export const TID_SENSOR_PRESS = "S2"
export const TID_SENSOR_ACCELEROMETER = "S3"
export const TID_SENSOR_TIMER = "S4"
export const TID_SENSOR_LIGHT = "S5"
export const TID_SENSOR_TEMP = "S6"
export const TID_SENSOR_RADIO_RECEIVE = "S7"
export const TID_SENSOR_MICROPHONE = "S8"
// filters for TID_SENSOR_PRESS
export const TID_FILTER_PIN_0 = "F0"
export const TID_FILTER_PIN_1 = "F1"
export const TID_FILTER_PIN_2 = "F2"
export const TID_FILTER_BUTTON_A = "F3"
export const TID_FILTER_BUTTON_B = "F4"
export const TID_FILTER_BUTTON_AB = "F5"
// F6
export const TID_FILTER_LOGO = "F7"
export const TID_FILTER_VALUE_1 = "F8"
export const TID_FILTER_VALUE_2 = "F9"
export const TID_FILTER_VALUE_3 = "F10"
export const TID_FILTER_VALUE_4 = "F11"
export const TID_FILTER_VALUE_5 = "F12"
export const TID_FILTER_TIMESPAN_SHORT = "F13"
export const TID_FILTER_TIMESPAN_LONG = "F14"
export const TID_ACTUATOR_SWITCH_PAGE = "A1"
export const TID_ACTUATOR_SPEAKER = "A2"
export const TID_ACTUATOR_MICROPHONE = "A3"
export const TID_ACTUATOR_MUSIC = "A4"
export const TID_ACTUATOR_PAINT = "A5"
export const TID_ACTUATOR_RADIO_SEND = "A6"
export const TID_MODIFIER_PAGE_1 = "M1"
export const TID_MODIFIER_PAGE_2 = "M2"
export const TID_MODIFIER_PAGE_3 = "M3"
export const TID_MODIFIER_PAGE_4 = "M4"
export const TID_MODIFIER_PAGE_5 = "M5"
export const TID_MODIFIER_VALUE_1 = "M6"
export const TID_MODIFIER_VALUE_2 = "M7"
export const TID_MODIFIER_VALUE_3 = "M8"
export const TID_MODIFIER_VALUE_4 = "M9"
export const TID_MODIFIER_VALUE_5 = "M10"
export const TID_MODIFIER_ON = "M11"
export const TID_MODIFIER_OFF = "M12"
export const TID_MODIFIER_ICON_EDITOR = "M15"
export const TID_MODIFIER_COLOR_RED = "M16"
export const TID_MODIFIER_COLOR_DARKPURPLE = "M17"
export const PAGE_IDS = [
TID_MODIFIER_PAGE_1,
TID_MODIFIER_PAGE_2,
TID_MODIFIER_PAGE_3,
TID_MODIFIER_PAGE_4,
TID_MODIFIER_PAGE_5,
]
export const tilesDB: TileDatabase = {
sensors: {},
filters: {},
actuators: {},
modifiers: {},
}
function copyJdSensor(dst: SensorDefn, src: SensorDefn) {
dst.serviceClassName = src.serviceClassName
dst.eventCode = src.eventCode
dst.serviceInstanceIndex = src.serviceInstanceIndex
}
function copyJdActuator(dst: ActuatorDefn, src: ActuatorDefn) {
dst.serviceClassName = src.serviceClassName
dst.serviceCommand = src.serviceCommand
dst.serviceInstanceIndex = src.serviceInstanceIndex
}
// initialize the database, imperatively!!!
const always = new SensorDefn(TID_SENSOR_ALWAYS, "Always", Phase.Pre)
always.hidden = true
tilesDB.sensors[TID_SENSOR_ALWAYS] = always
const press_event = new SensorDefn(TID_SENSOR_PRESS, "press", Phase.Pre)
press_event.serviceClassName = "button"
press_event.eventCode = 0x1 // down
press_event.serviceInstanceIndex = 0
press_event.constraints = {
provides: ["input"],
allow: {
categories: ["press_event"],
},
}
tilesDB.sensors[TID_SENSOR_PRESS] = press_event
function addPressFilter(tid: string, name: string, instanceNo: number) {
const press_filter = new FilterDefn(tid, name, "press_event", 10)
press_filter.constraints = {
handling: {
terminal: true,
},
allow: {
categories: ["press_event"],
},
}
tilesDB.filters[tid] = press_filter
press_filter.jdParam = instanceNo
}
addPressFilter(TID_FILTER_BUTTON_A, "A", 0)
addPressFilter(TID_FILTER_BUTTON_B, "B", 1)
addPressFilter(TID_FILTER_LOGO, "Logo", 2)
addPressFilter(TID_FILTER_PIN_0, "Pin 0", 3)
addPressFilter(TID_FILTER_PIN_1, "Pin 1", 4)
addPressFilter(TID_FILTER_PIN_2, "Pin 2", 5)
const radio_receive = new SensorDefn(
TID_SENSOR_RADIO_RECEIVE,
"Receive",
Phase.Post
)
radio_receive.constraints = {
allow: {
categories: ["value_in"],
},
}
tilesDB.sensors[TID_SENSOR_RADIO_RECEIVE] = radio_receive
const timer = new SensorDefn(
TID_SENSOR_TIMER,
"Timer",
Phase.Post
)
timer.constraints = {
allow: {
categories: ["timespan"],
},
}
tilesDB.sensors[TID_SENSOR_TIMER] = timer
function addTimespan(tid: string, name: string, ms: number) {
const timespan = new FilterDefn(tid, name, "timespan", 10)
timespan.jdParam = ms
tilesDB.filters[tid] = timespan
}
addTimespan(TID_FILTER_TIMESPAN_SHORT, "short", 250)
addTimespan(TID_FILTER_TIMESPAN_LONG, "long", 1000)
function addActuator(tid: string, name: string, allow: string) {
const actuator = new ActuatorDefn(tid, name)
actuator.constraints = {
allow: {
categories: [allow],
},
}
tilesDB.actuators[tid] = actuator
return actuator
}
addActuator(TID_ACTUATOR_SWITCH_PAGE, "Switch page", "page")
const paint = addActuator(TID_ACTUATOR_PAINT, "Paint", "icon_editor")
paint.serviceClassName = "dotMatrix"
paint.serviceCommand = jacs.CMD_SET_REG | 0x2
paint.serviceInstanceIndex = 0
addActuator(TID_ACTUATOR_RADIO_SEND, "Send", "value_out")
addActuator(TID_ACTUATOR_MICROPHONE, "Microphone", "on_off")
addActuator(TID_ACTUATOR_SPEAKER, "Speaker", "foo")
addActuator(TID_ACTUATOR_MUSIC, "Music", "bar")
const terminal = {
handling: {
terminal: true,
},
}
const make_vals = (name: string, kind: string, start: number) => {
for (let v = 1; v <= 5; v++) {
const tid = kind + (start + v - 1)
const tile =
kind == "M"
? new ModifierDefn(tid, name + " " + v.toString(), name, 10)
: new FilterDefn(tid, name + " " + v.toString(), name, 10)
tile.jdParam = v
tile.constraints = terminal
if (kind == "M") tilesDB.modifiers[tid] = tile
else tilesDB.filters[tid] = tile
}
}
make_vals("page", "M", 1)
make_vals("value_in", "F", 8)
make_vals("value_out", "M", 6)
const switch_states = ["on", "off"]
switch_states.forEach(state => {
const state_tid = state == "on" ? TID_MODIFIER_ON : TID_MODIFIER_OFF
const state_page = new ModifierDefn(state_tid, state, "on_off", 10)
state_page.constraints = terminal
tilesDB.modifiers[state_tid] = state_page
})
const iconFieldEditor: FieldEditor = {
init: img`
. . . . .
. . . . .
. . 1 . .
. . . . .
. . . . .
`,
clone: (img: Image) => img.clone(),
editor: iconEditor,
image: scaleUp,
serialize: (img: Image) => {
const ret: string[] = []
for (let index = 0; index < 25; index++) {
let col = index % 5
let row = index / 5
ret.push(img.getPixel(col, row) ? "1" : "0")
}
return ret.join("")
},
deserialize: (s: string) => {
const img = image.create(5, 5)
for (let index = 0; index < 25; index++) {
let col = index % 5
let row = index / 5
img.setPixel(col, row, s[index] == "1" ? 1 : 0)
}
return img
},
}
class IconEditor extends ModifierDefn {
field: Image
constructor(field: Image = null) {
super(TID_MODIFIER_ICON_EDITOR, "icon editor", "icon_editor", 10)
this.fieldEditor = iconFieldEditor
if (field) this.field = field
else this.field = iconFieldEditor.clone(iconFieldEditor.init)
}
getField() {
return this.field
}
getIcon(): Image {
return this.fieldEditor.image(this.field)
}
getNewInstance(field: any) {
const newOne = new IconEditor(field ? field : this.field.clone())
return newOne
}
serviceCommandArg() {
const buf = Buffer.create(5)
for (let col = 0; col < 5; ++col) {
let v = 0
for (let row = 0; row < 5; ++row) {
if (this.field.getPixel(col, row)) v |= 1 << row
}
buf[col] = v
}
return buf
}
}
tilesDB.modifiers[TID_MODIFIER_ICON_EDITOR] = new IconEditor()
}