summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/lightbar.c200
-rw-r--r--extra/lightbar/programs/bad-decode-32.bin2
-rw-r--r--extra/lightbar/programs/bad-decode-8.binbin2 -> 3 bytes
-rw-r--r--extra/lightbar/programs/bad-jump.binbin2 -> 2 bytes
-rw-r--r--extra/lightbar/programs/green-pulse.binbin23 -> 19 bytes
-rw-r--r--extra/lightbar/programs/green-pulse.lbs8
-rw-r--r--extra/lightbar/programs/infinite-jump.binbin2 -> 2 bytes
-rw-r--r--extra/lightbar/programs/infinite-jump.lbs1
-rw-r--r--extra/lightbar/programs/konami.binbin0 -> 144 bytes
-rw-r--r--extra/lightbar/programs/konami.lbs89
-rw-r--r--extra/lightbar/programs/rainbow-shift-compact.binbin36 -> 0 bytes
-rw-r--r--extra/lightbar/programs/rainbow-shift.binbin52 -> 31 bytes
-rw-r--r--extra/lightbar/programs/rainbow-shift.lbs8
-rw-r--r--extra/lightbar/programs/red-green-blink.binbin36 -> 29 bytes
-rw-r--r--extra/lightbar/programs/red-green-blink.lbs14
-rw-r--r--extra/lightbar/programs/s0.binbin0 -> 58 bytes
-rw-r--r--extra/lightbar/programs/s0.lbs22
-rw-r--r--extra/lightbar/programs/s0s3.binbin0 -> 43 bytes
-rw-r--r--extra/lightbar/programs/s0s3.lbs16
-rw-r--r--extra/lightbar/programs/s3.binbin0 -> 37 bytes
-rw-r--r--extra/lightbar/programs/s3.lbs17
-rw-r--r--extra/lightbar/programs/s3s0.binbin0 -> 34 bytes
-rw-r--r--extra/lightbar/programs/s3s0.lbs11
-rw-r--r--include/lightbar_opcode_list.h30
-rw-r--r--util/lbcc.c264
25 files changed, 541 insertions, 141 deletions
diff --git a/common/lightbar.c b/common/lightbar.c
index f8dce75c50..b6360c18f2 100644
--- a/common/lightbar.c
+++ b/common/lightbar.c
@@ -927,6 +927,7 @@ static struct lightbar_program next_prog;
static uint8_t pc;
static uint8_t led_desc[NUM_LEDS][LB_CONT_MAX][3];
+static uint32_t lb_wait_delay;
static uint32_t lb_ramp_delay;
/* Get one byte of data pointed to by the pc and advance
* the pc forward.
@@ -957,6 +958,20 @@ static inline uint32_t decode_32(uint32_t *dest)
return EC_SUCCESS;
}
+/* ON - turn on lightbar */
+static uint32_t lightbyte_ON(void)
+{
+ lb_on();
+ return EC_SUCCESS;
+}
+
+/* OFF - turn off lightbar */
+static uint32_t lightbyte_OFF(void)
+{
+ lb_off();
+ return EC_SUCCESS;
+}
+
/* JUMP xx - jump to immediate location
* Changes the pc to the one-byte immediate argument.
*/
@@ -965,17 +980,72 @@ static uint32_t lightbyte_JUMP(void)
return decode_8(&pc);
}
-/* DELAY xx xx xx xx - yield processor for some time
- * Performs an interruptible wait for a number of microseconds
- * given in the four-byte immediate.
+/* JUMP_BATTERY aa bb - switch on battery level
+ * If the battery is low, changes pc to aa.
+ * If the battery is high, changes pc to bb.
+ * Otherwise, continues execution as normal.
*/
-static uint32_t lightbyte_DELAY(void)
+static uint32_t lightbyte_JUMP_BATTERY(void)
{
- uint32_t delay_us;
- if (decode_32(&delay_us) != EC_SUCCESS)
+ uint8_t low_pc, high_pc;
+ if (decode_8(&low_pc) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
+ if (decode_8(&high_pc) != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
- WAIT_OR_RET(delay_us);
+ get_battery_level();
+ if (st.battery_level == 0)
+ pc = low_pc;
+ else if (st.battery_level == 3)
+ pc = high_pc;
+
+ return EC_SUCCESS;
+}
+
+/* JUMP_IF_CHARGING xx - conditional jump to location
+ * Changes the pc to xx if the device is charging.
+ */
+static uint32_t lightbyte_JUMP_IF_CHARGING(void)
+{
+ uint8_t charge_pc;
+ if (decode_8(&charge_pc) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
+
+ if (st.battery_is_charging)
+ pc = charge_pc;
+
+ return EC_SUCCESS;
+}
+
+/* SET_WAIT_DELAY xx xx xx xx - set up to yield processor
+ * Sets the wait delay to the given four-byte immediate, in
+ * microseconds. Future WAIT instructions will wait for this
+ * much time.
+ */
+static uint32_t lightbyte_SET_WAIT_DELAY(void)
+{
+ return decode_32(&lb_wait_delay);
+}
+
+/* SET_RAMP_DELAY xx xx xx xx - change ramp speed
+ * This sets the length of time between ramp/cycle steps to
+ * the four-byte immediate argument, which represents a duration
+ * in milliseconds.
+ */
+static uint32_t lightbyte_SET_RAMP_DELAY(void)
+{
+ return decode_32(&lb_ramp_delay);
+}
+
+/* WAIT - yield processor for some time
+ * Yields the processor for some amount of time set by the most
+ * recent SET_WAIT_DELAY instruction.
+ */
+static uint32_t lightbyte_WAIT(void)
+{
+ if (lb_wait_delay != 0)
+ WAIT_OR_RET(lb_wait_delay);
+
return EC_SUCCESS;
}
@@ -993,33 +1063,34 @@ static uint32_t lightbyte_SET_BRIGHTNESS(void)
return EC_SUCCESS;
}
-/* SET_COLOR cc xx
- * SET_COLOR cc rr gg bb
+/* SET_COLOR_SINGLE cc xx
+ * SET_COLOR_RGB cc rr gg bb
* Stores a color value in the led_desc structure.
* cc is a bit-packed location to perform the action on.
*
- * The high four bits are used to describe an LED. If the
- * value is less than NUM_LEDS, it describes a particular LED,
- * and if it is greater than or equal to that value, it
- * will perform the action on all LEDs.
+ * The high four bits are a bitset for which LEDs to operate on.
+ * LED 0 is the lowest of the four bits.
*
* The next two bits are the control bits. This should be a value
* in lb_control that is not LB_CONT_MAX, and the corresponding
* color will be the one the action is performed on.
*
- * The last two bits are the color bits. If this is LB_COL_RED,
- * LB_COL_GREEN, or LB_COL_BLUE, then there is only one more byte
- * to decode and this is a color value for that specific color
- * channel. If it is LB_COL_ALL, then there are three more bytes,
- * and it reads like a standard 24-bit color value.
+ * The last two bits are the color bits if this instruction is
+ * SET_COLOR_SINGLE. They correspond to a LB_COL value for the
+ * channel to set the color for using the next immediate byte.
+ * In SET_COLOR_RGB, these bits are don't-cares, as there should
+ * always be three bytes that follow, which correspond to a
+ * complete RGB specification.
*/
-static uint32_t lightbyte_SET_COLOR(void)
+static uint32_t lightbyte_SET_COLOR_SINGLE(void)
{
uint8_t packed_loc, led, control, color, value;
- int start_led, end_led, color_mask, i, j;
+ int i;
if (decode_8(&packed_loc) != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
+ if (decode_8(&value) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
led = packed_loc >> 4;
control = (packed_loc >> 2) & 0x3;
@@ -1028,34 +1099,74 @@ static uint32_t lightbyte_SET_COLOR(void)
if (control >= LB_CONT_MAX)
return EC_RES_INVALID_PARAM;
- if (led >= NUM_LEDS) {
- start_led = 0;
- end_led = NUM_LEDS - 1;
- } else
- start_led = end_led = led;
+ for (i = 0; i < NUM_LEDS; i++)
+ if (led & (1 << i))
+ led_desc[i][control][color] = value;
+
+ return EC_SUCCESS;
+}
+
+static uint32_t lightbyte_SET_COLOR_RGB(void)
+{
+ uint8_t packed_loc, r, g, b, led, control;
+ int i;
+
+ /* gross */
+ if (decode_8(&packed_loc) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
+ if (decode_8(&r) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
+ if (decode_8(&g) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
+ if (decode_8(&b) != EC_SUCCESS)
+ return EC_RES_INVALID_PARAM;
+
+ led = packed_loc >> 4;
+ control = (packed_loc >> 2) & 0x3;
- color_mask = color == LB_COL_ALL ? 7 : (1 << color);
+ if (control >= LB_CONT_MAX)
+ return EC_RES_INVALID_PARAM;
- for (i = 0; i < 3; i++) {
- if (color_mask & (1 << i)) {
- if (decode_8(&value) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- for (j = start_led; j <= end_led; j++)
- led_desc[j][control][i] = value;
+ for (i = 0; i < NUM_LEDS; i++)
+ if (led & (1 << i)) {
+ led_desc[i][control][LB_COL_RED] = r;
+ led_desc[i][control][LB_COL_GREEN] = g;
+ led_desc[i][control][LB_COL_BLUE] = b;
}
- }
return EC_SUCCESS;
}
-/* SET_DELAY_TIME xx xx xx xx - change ramp speed
- * This sets the length of time between ramp/cycle steps to
- * the four-byte immediate argument, which represents a duration
- * in milliseconds.
+/* GET_COLORS - take current colors and push them to the state
+ * Gets the current state of the LEDs and puts them in COLOR0.
+ * Good for the beginning of a program if you need to fade in.
*/
-static uint32_t lightbyte_SET_DELAY_TIME(void)
+static uint32_t lightbyte_GET_COLORS(void)
{
- return decode_32(&lb_ramp_delay);
+ int i;
+ for (i = 0; i < NUM_LEDS; i++)
+ lb_get_rgb(i, &led_desc[i][LB_CONT_COLOR0][LB_COL_RED],
+ &led_desc[i][LB_CONT_COLOR0][LB_COL_GREEN],
+ &led_desc[i][LB_CONT_COLOR0][LB_COL_BLUE]);
+
+ return EC_SUCCESS;
+}
+
+/* SWAP_COLORS - swaps beginning and end colors in state
+ * Exchanges COLOR0 and COLOR1 on all LEDs.
+ */
+static uint32_t lightbyte_SWAP_COLORS(void)
+{
+ int i, j, tmp;
+ for (i = 0; i < NUM_LEDS; i++)
+ for (j = 0; j < 3; j++) {
+ tmp = led_desc[i][LB_CONT_COLOR0][j];
+ led_desc[i][LB_CONT_COLOR0][j] =
+ led_desc[i][LB_CONT_COLOR1][j];
+ led_desc[i][LB_CONT_COLOR1][j] = tmp;
+ }
+
+ return EC_SUCCESS;
}
static inline int get_interp_value(int led, int color, int interp)
@@ -1173,7 +1284,7 @@ static uint32_t lightbyte_HALT(void)
#undef GET_INTERP_VALUE
-#define OP(X) X
+#define OP(NAME, BYTES, MNEMONIC) NAME,
#include "lightbar_opcode_list.h"
enum lightbyte_opcode {
LIGHTBAR_OPCODE_TABLE
@@ -1181,14 +1292,14 @@ enum lightbyte_opcode {
};
#undef OP
-#define OP(X) lightbyte_ ## X
+#define OP(NAME, BYTES, MNEMONIC) lightbyte_ ## NAME,
#include "lightbar_opcode_list.h"
static uint32_t (*lightbyte_dispatch[])(void) = {
LIGHTBAR_OPCODE_TABLE
};
#undef OP
-#define OP(X) # X
+#define OP(NAME, BYTES, MNEMONIC) MNEMONIC,
#include "lightbar_opcode_list.h"
static const char * const lightbyte_names[] = {
LIGHTBAR_OPCODE_TABLE
@@ -1209,8 +1320,12 @@ static uint32_t sequence_PROGRAM(void)
saved_brightness = lb_get_brightness();
pc = 0;
memset(led_desc, 0, sizeof(led_desc));
+ lb_wait_delay = 0;
lb_ramp_delay = 0;
+ lb_on();
+ lb_set_brightness(255);
+
/* decode-execute loop */
for (;;) {
old_pc = pc;
@@ -1582,6 +1697,7 @@ static int command_lightbar(int argc, char **argv)
}
#ifdef LIGHTBAR_SIMULATION
+ /* Load a program. */
if (argc >= 3 && !strcasecmp(argv[1], "program")) {
return lb_load_program(argv[2], &next_prog);
}
diff --git a/extra/lightbar/programs/bad-decode-32.bin b/extra/lightbar/programs/bad-decode-32.bin
index de2e71b327..1d5d0c6c75 100644
--- a/extra/lightbar/programs/bad-decode-32.bin
+++ b/extra/lightbar/programs/bad-decode-32.bin
@@ -1 +1 @@
-UUU \ No newline at end of file
+UUU \ No newline at end of file
diff --git a/extra/lightbar/programs/bad-decode-8.bin b/extra/lightbar/programs/bad-decode-8.bin
index d8188da697..8352675d67 100644
--- a/extra/lightbar/programs/bad-decode-8.bin
+++ b/extra/lightbar/programs/bad-decode-8.bin
Binary files differ
diff --git a/extra/lightbar/programs/bad-jump.bin b/extra/lightbar/programs/bad-jump.bin
index d284cb97ce..b2c29a0bbf 100644
--- a/extra/lightbar/programs/bad-jump.bin
+++ b/extra/lightbar/programs/bad-jump.bin
Binary files differ
diff --git a/extra/lightbar/programs/green-pulse.bin b/extra/lightbar/programs/green-pulse.bin
index 9ea21f789a..0fdab712e9 100644
--- a/extra/lightbar/programs/green-pulse.bin
+++ b/extra/lightbar/programs/green-pulse.bin
Binary files differ
diff --git a/extra/lightbar/programs/green-pulse.lbs b/extra/lightbar/programs/green-pulse.lbs
new file mode 100644
index 0000000000..bccf3e5c9a
--- /dev/null
+++ b/extra/lightbar/programs/green-pulse.lbs
@@ -0,0 +1,8 @@
+ set.1 {0,1,2,3}.end.g 0xff
+ delay.r 7813
+ delay.w 2000000
+L0001: on
+ cycle.1
+ off
+ wait
+ jump L0001
diff --git a/extra/lightbar/programs/infinite-jump.bin b/extra/lightbar/programs/infinite-jump.bin
index 09f370e38f..5407bf3ddf 100644
--- a/extra/lightbar/programs/infinite-jump.bin
+++ b/extra/lightbar/programs/infinite-jump.bin
Binary files differ
diff --git a/extra/lightbar/programs/infinite-jump.lbs b/extra/lightbar/programs/infinite-jump.lbs
new file mode 100644
index 0000000000..6174d7ffd4
--- /dev/null
+++ b/extra/lightbar/programs/infinite-jump.lbs
@@ -0,0 +1 @@
+L0001: jump L0001
diff --git a/extra/lightbar/programs/konami.bin b/extra/lightbar/programs/konami.bin
new file mode 100644
index 0000000000..f7abfdc4ee
--- /dev/null
+++ b/extra/lightbar/programs/konami.bin
Binary files differ
diff --git a/extra/lightbar/programs/konami.lbs b/extra/lightbar/programs/konami.lbs
new file mode 100644
index 0000000000..c9fa8d697a
--- /dev/null
+++ b/extra/lightbar/programs/konami.lbs
@@ -0,0 +1,89 @@
+# Konami code easter egg
+ delay.w 100000
+ set.rgb {1,2}.end 0xff 0xff 0x00
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ set.rgb {1,2}.end 0x00 0x00 0x00
+ set.1 {0,3}.end.b 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ set.1 {0,3}.end.b 0x00
+ set.1 {0,1}.end.r 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ set.1 {0,1}.end.r 0x00
+ set.1 {2,3}.end.g 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ set.1 {2,3}.end.g 0x00
+ set.1 {0,1}.end.r 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ set.1 {0,1}.end.r 0x00
+ set.1 {2,3}.end.g 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ set.1 {2,3}.end.g 0x00
+ set.rgb {0,2}.end 0x00 0xff 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ delay.w 50000
+ wait
+ set.rgb {0,2}.end 0x00 0x00 0x00
+ set.rgb {1,3}.end 0xff 0x00 0xff
+ ramp.1
+ wait
+ wait
+ cycle.1
+ wait
+ delay.w 100000
+ wait
+ wait
+ set.rgb {0,1,2,3}.end 0xff 0xff 0xff
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ halt
diff --git a/extra/lightbar/programs/rainbow-shift-compact.bin b/extra/lightbar/programs/rainbow-shift-compact.bin
deleted file mode 100644
index f5590c5820..0000000000
--- a/extra/lightbar/programs/rainbow-shift-compact.bin
+++ /dev/null
Binary files differ
diff --git a/extra/lightbar/programs/rainbow-shift.bin b/extra/lightbar/programs/rainbow-shift.bin
index 44e1af4b7d..a72c5b16d6 100644
--- a/extra/lightbar/programs/rainbow-shift.bin
+++ b/extra/lightbar/programs/rainbow-shift.bin
Binary files differ
diff --git a/extra/lightbar/programs/rainbow-shift.lbs b/extra/lightbar/programs/rainbow-shift.lbs
new file mode 100644
index 0000000000..e1cbcddc83
--- /dev/null
+++ b/extra/lightbar/programs/rainbow-shift.lbs
@@ -0,0 +1,8 @@
+# The rainbow cycle program.
+ set.rgb {0,1,2,3}.end 0xff 0xff 0xff
+ set.rgb {0}.phase 0x00 0x55 0xaa
+ set.rgb {1}.phase 0x40 0x95 0xea
+ set.rgb {2}.phase 0x80 0xd5 0x2a
+ set.rgb {3}.phase 0xc0 0x15 0x6a
+ delay.r 7813
+ cycle
diff --git a/extra/lightbar/programs/red-green-blink.bin b/extra/lightbar/programs/red-green-blink.bin
index 305f3c53f9..6bece444dd 100644
--- a/extra/lightbar/programs/red-green-blink.bin
+++ b/extra/lightbar/programs/red-green-blink.bin
Binary files differ
diff --git a/extra/lightbar/programs/red-green-blink.lbs b/extra/lightbar/programs/red-green-blink.lbs
new file mode 100644
index 0000000000..d520b739bb
--- /dev/null
+++ b/extra/lightbar/programs/red-green-blink.lbs
@@ -0,0 +1,14 @@
+# Blinks red and green with 1 second pauses.
+ set.rgb {0,1,2,3}.beg 0xff 0x00 0x00
+ set.rgb {0,1,2,3}.end 0x00 0xff 0x00
+ delay.w 250000
+ delay.r 0
+ cycle.1
+ wait
+ ramp.1
+ wait
+ cycle.1
+ wait
+ ramp.1
+ wait
+ halt
diff --git a/extra/lightbar/programs/s0.bin b/extra/lightbar/programs/s0.bin
new file mode 100644
index 0000000000..b20cecd8ee
--- /dev/null
+++ b/extra/lightbar/programs/s0.bin
Binary files differ
diff --git a/extra/lightbar/programs/s0.lbs b/extra/lightbar/programs/s0.lbs
new file mode 100644
index 0000000000..364c3d595c
--- /dev/null
+++ b/extra/lightbar/programs/s0.lbs
@@ -0,0 +1,22 @@
+# S0 sequence: Google colors, unless battery is low.
+ set.rgb {0}.end 0x33 0x69 0xe8
+ set.rgb {1}.end 0xd5 0x0f 0x25
+ set.rgb {2}.end 0xee 0xb2 0x11
+ set.rgb {3}.end 0x00 0x99 0x25
+ delay.r 1250
+ ramp.1
+ set.1 {0,1,2,3}.beg.r 0xff
+ delay.r 2500
+ delay.w 1000000
+ wait
+ jump L0003
+L0001: swap
+ ramp.1
+L0002: wait
+L0003: jbat L0004 L0002
+ jump L0002
+L0004: swap
+ ramp.1
+L0005: wait
+ jbat L0005 L0001
+ jump L0001
diff --git a/extra/lightbar/programs/s0s3.bin b/extra/lightbar/programs/s0s3.bin
new file mode 100644
index 0000000000..d1cb8a4af1
--- /dev/null
+++ b/extra/lightbar/programs/s0s3.bin
Binary files differ
diff --git a/extra/lightbar/programs/s0s3.lbs b/extra/lightbar/programs/s0s3.lbs
new file mode 100644
index 0000000000..ba141f338d
--- /dev/null
+++ b/extra/lightbar/programs/s0s3.lbs
@@ -0,0 +1,16 @@
+# S0S3 sequence: Fade out, Google color ramp up/down.
+ get
+ delay.r 2000
+ ramp.1
+ swap
+ set.rgb {0}.end 0x33 0x69 0xe8
+ set.rgb {1}.end 0xd5 0x0f 0x25
+ set.rgb {2}.end 0xee 0xb2 0x11
+ set.rgb {3}.end 0x00 0x99 0x25
+ delay.r 1250
+ ramp.1
+ swap
+ delay.r 10000
+ ramp.1
+ off
+ halt
diff --git a/extra/lightbar/programs/s3.bin b/extra/lightbar/programs/s3.bin
new file mode 100644
index 0000000000..7e487bb8c9
--- /dev/null
+++ b/extra/lightbar/programs/s3.bin
Binary files differ
diff --git a/extra/lightbar/programs/s3.lbs b/extra/lightbar/programs/s3.lbs
new file mode 100644
index 0000000000..e8803a06bb
--- /dev/null
+++ b/extra/lightbar/programs/s3.lbs
@@ -0,0 +1,17 @@
+# S3 sequence: Pulse red on low battery.
+ set.rgb {0,1,2,3}.end 0xff 0x00 0x00
+ cycle.1
+ delay.w 5000000
+L0001: off
+ wait
+ jcharge L0001
+ jbat L0002 L0001
+ jump L0001
+L0002: on
+ delay.r 1250
+ ramp.1
+ swap
+ delay.r 10000
+ ramp.1
+ swap
+ jump L0001
diff --git a/extra/lightbar/programs/s3s0.bin b/extra/lightbar/programs/s3s0.bin
new file mode 100644
index 0000000000..b277752d25
--- /dev/null
+++ b/extra/lightbar/programs/s3s0.bin
Binary files differ
diff --git a/extra/lightbar/programs/s3s0.lbs b/extra/lightbar/programs/s3s0.lbs
new file mode 100644
index 0000000000..0cac96f208
--- /dev/null
+++ b/extra/lightbar/programs/s3s0.lbs
@@ -0,0 +1,11 @@
+# S3S0 sequence: Google color ramp up/down.
+ set.rgb {0}.end 0x33 0x69 0xe8
+ set.rgb {1}.end 0xd5 0x0f 0x25
+ set.rgb {2}.end 0xee 0xb2 0x11
+ set.rgb {3}.end 0x00 0x99 0x25
+ delay.r 1250
+ ramp.1
+ swap
+ delay.r 10000
+ ramp.1
+ halt
diff --git a/include/lightbar_opcode_list.h b/include/lightbar_opcode_list.h
index 83432c04e3..14ab23421c 100644
--- a/include/lightbar_opcode_list.h
+++ b/include/lightbar_opcode_list.h
@@ -4,13 +4,23 @@
*
* This defines a list of lightbar opcodes for programmable sequences.
*/
-#define LIGHTBAR_OPCODE_TABLE \
- OP(JUMP), \
- OP(DELAY), \
- OP(SET_BRIGHTNESS), \
- OP(SET_COLOR), \
- OP(SET_DELAY_TIME), \
- OP(RAMP_ONCE), \
- OP(CYCLE_ONCE), \
- OP(CYCLE), \
- OP(HALT),
+
+/* NAME OPERAND BYTES MNEMONIC*/
+#define LIGHTBAR_OPCODE_TABLE \
+ OP(ON, 0, "on" )\
+ OP(OFF, 0, "off" )\
+ OP(JUMP, 1, "jump" )\
+ OP(JUMP_BATTERY, 2, "jbat" )\
+ OP(JUMP_IF_CHARGING, 1, "jcharge" )\
+ OP(SET_WAIT_DELAY, 4, "delay.w" )\
+ OP(SET_RAMP_DELAY, 4, "delay.r" )\
+ OP(WAIT, 0, "wait" )\
+ OP(SET_BRIGHTNESS, 1, "bright" )\
+ OP(SET_COLOR_SINGLE, 2, "set.1" )\
+ OP(SET_COLOR_RGB, 4, "set.rgb" )\
+ OP(GET_COLORS, 0, "get" )\
+ OP(SWAP_COLORS, 0, "swap" )\
+ OP(RAMP_ONCE, 0, "ramp.1" )\
+ OP(CYCLE_ONCE, 0, "cycle.1" )\
+ OP(CYCLE, 0, "cycle" )\
+ OP(HALT, 0, "halt" )
diff --git a/util/lbcc.c b/util/lbcc.c
index a5247dcccc..b34b21e53e 100644
--- a/util/lbcc.c
+++ b/util/lbcc.c
@@ -64,7 +64,7 @@ struct safe_lightbar_program {
uint8_t zeros[LB_PROG_MAX_OPERANDS];
} __packed;
-#define OP(X) X
+#define OP(NAME, BYTES, MNEMONIC) NAME,
#include "lightbar_opcode_list.h"
enum lightbyte_opcode {
LIGHTBAR_OPCODE_TABLE
@@ -72,18 +72,25 @@ enum lightbyte_opcode {
};
#undef OP
+#define OP(NAME, BYTES, MNEMONIC) BYTES,
+#include "lightbar_opcode_list.h"
+static const int num_operands[] = {
+ LIGHTBAR_OPCODE_TABLE
+};
+#undef OP
+
+#define OP(NAME, BYTES, MNEMONIC) MNEMONIC,
+#include "lightbar_opcode_list.h"
static const char const *opcode_sym[] = {
- "jump", "wait", "bright", "color",
- "step", "ramp.1", "cycle.1", "cycle",
- "halt",
+ LIGHTBAR_OPCODE_TABLE
};
-BUILD_ASSERT(ARRAY_SIZE(opcode_sym) == MAX_OPCODE);
+#undef OP
static const char const *control_sym[] = {
"beg", "end", "phase", "<invalid>"
};
static const char const *color_sym[] = {
- "r", "g", "b", "rgb"
+ "r", "g", "b", "<invalid>"
};
static void read_binary(FILE *fp, struct safe_lightbar_program *prog)
@@ -111,35 +118,6 @@ static void read_binary(FILE *fp, struct safe_lightbar_program *prog)
}
}
-/* Returns number of operands required by an opcode */
-static int num_operands(uint8_t cmd, uint8_t *arg)
-{
- int operands = 0;
-
- switch (cmd) {
- case JUMP:
- case SET_BRIGHTNESS:
- operands = 1;
- break;
-
- case DELAY:
- case SET_DELAY_TIME:
- operands = 4;
- break;
-
- case SET_COLOR:
- if ((arg[0] & 0x03) == LB_COL_ALL)
- operands = 4;
- else
- operands = 2;
- break;
-
- default:
- break;
- }
- return operands;
-}
-
static uint32_t val32(uint8_t *ptr)
{
uint32_t val;
@@ -147,13 +125,34 @@ static uint32_t val32(uint8_t *ptr)
return val;
}
+static int is_jump(uint8_t op)
+{
+ /* TODO: probably should be a field in the opcode list */
+ return op >= JUMP && op <= JUMP_IF_CHARGING;
+}
+
+static void print_led_set(FILE *fp, uint8_t led)
+{
+ int i, first = 1;
+
+ fprintf(fp, "{");
+ for (i = 0; i < NUM_LEDS; i++)
+ if (led & (1 << i)) {
+ if (!first)
+ fprintf(fp, ",");
+ fprintf(fp, "%d", i);
+ first = 0;
+ }
+ fprintf(fp, "}");
+}
+
/* returns number of operands consumed */
static int print_op(FILE *fp, uint8_t addr, uint8_t cmd, uint8_t *arg)
{
uint8_t led, color, control;
int i, operands;
- operands = num_operands(cmd, arg);
+ operands = num_operands[cmd];
/* assume valid instruction for now */
is_instruction[addr] = 1;
@@ -176,32 +175,44 @@ static int print_op(FILE *fp, uint8_t addr, uint8_t cmd, uint8_t *arg)
switch (cmd) {
case JUMP:
+ case JUMP_IF_CHARGING:
fprintf(fp, "\tL00%02x\n", arg[0]);
break;
- case DELAY:
- case SET_DELAY_TIME:
+ case JUMP_BATTERY:
+ fprintf(fp, "\tL00%02x L00%02x\n", arg[0], arg[1]);
+ break;
+ case SET_WAIT_DELAY:
+ case SET_RAMP_DELAY:
fprintf(fp, "\t%d\n", val32(arg));
break;
case SET_BRIGHTNESS:
fprintf(fp, "\t%d\n", arg[0]);
break;
- case SET_COLOR:
+ case SET_COLOR_SINGLE:
led = arg[0] >> 4;
control = (arg[0] >> 2) & 0x03;
color = arg[0] & 0x03;
fprintf(fp, "\t");
- if (led >= NUM_LEDS)
- fprintf(fp, "all");
- else
- fprintf(fp, "%d", led);
+
+ print_led_set(fp, led);
fprintf(fp, ".%s", control_sym[control]);
fprintf(fp, ".%s", color_sym[color]);
- if (color == LB_COL_ALL)
- fprintf(fp, "\t0x%02x 0x%02x 0x%02x\n",
- arg[1], arg[2], arg[3]);
- else
- fprintf(fp, "\t0x%02x\n", arg[1]);
+ fprintf(fp, "\t0x%02x\n", arg[1]);
break;
+ case SET_COLOR_RGB:
+ led = arg[0] >> 4;
+ control = (arg[0] >> 2) & 0x03;
+ fprintf(fp, "\t");
+
+ print_led_set(fp, led);
+ fprintf(fp, ".%s", control_sym[control]);
+ fprintf(fp, "\t0x%02x 0x%02x 0x%02x\n", arg[1], arg[2], arg[3]);
+ break;
+ case ON:
+ case OFF:
+ case WAIT:
+ case GET_COLORS:
+ case SWAP_COLORS:
case RAMP_ONCE:
case CYCLE_ONCE:
case CYCLE:
@@ -217,20 +228,31 @@ static int print_op(FILE *fp, uint8_t addr, uint8_t cmd, uint8_t *arg)
return operands;
}
+static void set_jump_target(uint8_t targ)
+{
+ if (targ >= EC_LB_PROG_LEN) {
+ Warning("program jumps to 0x%02x, "
+ "which out of bounds\n", targ);
+ return;
+ }
+ is_jump_target[targ] = 1;
+}
+
static void disassemble_prog(FILE *fp, struct safe_lightbar_program *prog)
{
int i;
- uint8_t *ptr, targ;
+ uint8_t *ptr, op;
/* Scan the program once to identify all the jump targets,
* so we can print the labels when we encounter them. */
for (i = 0; i < prog->p.size; i++) {
ptr = &prog->p.data[i];
- if (ptr[0] == JUMP) {
- targ = ptr[1];
- is_jump_target[targ] = 1;
- }
- i += num_operands(*ptr, ptr + 1);
+ op = *ptr;
+ if (is_jump(op))
+ set_jump_target(ptr[1]);
+ if (op == JUMP_BATTERY)
+ set_jump_target(ptr[2]);
+ i += num_operands[op];
}
/* Now disassemble */
@@ -278,28 +300,60 @@ static int split_line(char *buf, char *delim, struct parse_s *elt, int max)
return i;
}
-/* Decode color arg. Return 0 if bogus, number of additional args if okay. */
-static int is_color_arg(char *buf, uint32_t *valp)
+/* Decode led set. Return 0 if bogus, 1 if okay. */
+static int is_led_set(char *buf, uint8_t *valp)
+{
+ uint8_t led = 0;
+ unsigned long int next_led;
+ char *ptr;
+
+ if (!buf)
+ return 0;
+
+ if (*buf != '{')
+ return 0;
+
+ buf++;
+ for (;;) {
+ next_led = strtoul(buf, &ptr, 0);
+ if (buf == ptr) {
+ if (buf[0] == '}' && buf[1] == 0) {
+ *valp = led;
+ return 1;
+ } else
+ return 0;
+ }
+
+ if (next_led >= NUM_LEDS)
+ return 0;
+
+ led |= 1 << next_led;
+
+ buf = ptr;
+ if (*buf == ',')
+ buf++;
+ }
+}
+
+/* Decode color arg based on expected control param sections.
+ * Return 0 if bogus, 1 if okay.
+ */
+static int is_color_arg(char *buf, int expected, uint32_t *valp)
{
struct parse_s token[MAX_WORDS];
- uint8_t led, control, color, val;
- int i;
- int rv = 1;
+ uint8_t led, control, color;
+ int i;
if (!buf)
return 0;
/* There should be three terms, separated with '.' */
- i = split_line(buf, ".,", token, MAX_WORDS);
- if (i != 3)
+ i = split_line(buf, ".", token, MAX_WORDS);
+ if (i != expected)
return 0;
- if (!strcmp("all", token[0].word)) {
- led = NUM_LEDS;
- } else if (token[0].is_num) {
- led = token[0].val;
- } else {
- Error("Invalid LED \"%s\"\n", token[0].word);
+ if (!is_led_set(token[0].word, &led)) {
+ Error("Invalid LED set \"%s\"\n", token[0].word);
return 0;
}
@@ -311,22 +365,20 @@ static int is_color_arg(char *buf, uint32_t *valp)
if (i >= LB_CONT_MAX)
return 0;
- for (i = 0; i < ARRAY_SIZE(color_sym); i++)
- if (!strcmp(token[2].word, color_sym[i])) {
- color = i;
- break;
- }
- if (i >= ARRAY_SIZE(color_sym))
- return 0;
-
-
- val = ((led & 0xF) << 4) | ((control & 0x3) << 2) | (color & 0x3);
+ if (expected == 3) {
+ for (i = 0; i < ARRAY_SIZE(color_sym); i++)
+ if (!strcmp(token[2].word, color_sym[i])) {
+ color = i;
+ break;
+ }
+ if (i >= ARRAY_SIZE(color_sym))
+ return 0;
+ } else
+ color = 0;
- *valp = val;
- if (color == LB_COL_ALL)
- rv = 3;
- return rv;
+ *valp = ((led & 0xF) << 4) | ((control & 0x3) << 2) | (color & 0x3);
+ return 1;
}
static void fixup_symbols(struct safe_lightbar_program *prog)
@@ -422,12 +474,29 @@ static void compile(FILE *fp, struct safe_lightbar_program *prog)
/* Now we need operands. */
switch (opcode) {
case JUMP:
+ case JUMP_IF_CHARGING:
/* a label */
if (token[wnum].word)
reloc_label[addr++] = strdup(token[wnum].word);
else
Error("Missing jump target at line %d\n", line);
break;
+ case JUMP_BATTERY:
+ /* two labels*/
+ if (token[wnum].word)
+ reloc_label[addr++] = strdup(token[wnum].word);
+ else {
+ Error("Missing first jump target "
+ "at line %d\n", line);
+ break;
+ }
+ wnum++;
+ if (token[wnum].word)
+ reloc_label[addr++] = strdup(token[wnum].word);
+ else
+ Error("Missing second jump target "
+ "at line %d\n", line);
+ break;
case SET_BRIGHTNESS:
/* one 8-bit arg */
@@ -437,8 +506,8 @@ static void compile(FILE *fp, struct safe_lightbar_program *prog)
Error("Missing/invalid arg at line %d\n", line);
break;
- case DELAY:
- case SET_DELAY_TIME:
+ case SET_WAIT_DELAY:
+ case SET_RAMP_DELAY:
/* one 32-bit arg */
if (token[wnum].is_num) {
prog->p.data[addr++] =
@@ -454,17 +523,36 @@ static void compile(FILE *fp, struct safe_lightbar_program *prog)
}
break;
- case SET_COLOR:
- /* one magic word, then one or three more 8-bit args */
- i = is_color_arg(token[wnum].word, &token[wnum].val);
+ case SET_COLOR_SINGLE:
+ /* one magic word, then one more 8-bit arg */
+ i = is_color_arg(token[wnum].word, 3, &token[wnum].val);
+ if (!i) {
+ Error("Missing/invalid arg at line %d\n", line);
+ break;
+ }
+ /* save the magic number */
+ prog->p.data[addr++] = token[wnum++].val;
+ /* and the color immediate */
+ if (token[wnum].is_num) {
+ prog->p.data[addr++] =
+ token[wnum++].val;
+ } else {
+ Error("Missing/Invalid arg "
+ "at line %d\n", line);
+ break;
+ }
+ break;
+ case SET_COLOR_RGB:
+ /* one magic word, then three more 8-bit args */
+ i = is_color_arg(token[wnum].word, 2, &token[wnum].val);
if (!i) {
Error("Missing/invalid arg at line %d\n", line);
break;
}
/* save the magic number */
prog->p.data[addr++] = token[wnum++].val;
- while (i--) {
- /* and the others */
+ /* and the color immediates */
+ for (i = 0; i < 3; i++) {
if (token[wnum].is_num) {
prog->p.data[addr++] =
token[wnum++].val;