Skip to main content

๐Ÿ“š Test Code Library

This file stores code examples that are being tested and verified.


Moon Phase Simulation (12-Position LED)โ€‹

12 WS2812B LEDs arranged in a circle, simulating the moon's cycle from New Moon โ†’ First Quarter โ†’ Full Moon โ†’ Last Quarter โ†’ New Moon. LEDs use yellow light (R=77, G=77, B=00) with 4 brightness levels (77=High, 33=Medium, 11=Low, 00=Off). Each phase uses E5 batch instructions to set specific LED combinations to simulate realistic moon shape โ€” lit LEDs form a crescent/half/gibbous pattern rather than sequential lighting.

Core Opcodes: FZ (10) init ยท E5 batch set LED colors via registers ยท YS (02) delay ยท ZY (0E) unconditional jump

E5 Instruction Format: E5 OP00+OP01 OP10+OP11

  • OP00: Starting register number
  • OP01: 00=low byte, 01=high byte
  • OP10: Starting LED number
  • OP11: Number of LEDs to set

Register Plan:

RegisterValuePurpose
R017700Yellow high-brightness R
R027700Yellow high-brightness G
R030000Yellow high-brightness B
R043300Yellow medium-brightness R
R053300Yellow medium-brightness G
R060000Yellow medium-brightness B
R071100Yellow low-brightness R
R081100Yellow low-brightness G
R090000Yellow low-brightness B
R100000Off R (black)
R110000Off G (black)
R120000Off B (black)
R200080Delay duration (80 cycles per phase)

E5 Usage Examples:

CommandEffect
E5 0A01 000CAll LEDs off (R10-R12 high bytes, all 12 LEDs)
E5 0101 0003LED0-LED2 high-brightness yellow
E5 0401 0504LED5-LED8 medium-brightness yellow
E5 0701 0B01LED11 low-brightness yellow

12 Phase Cycle: New Moon โ†’ Waxing Crescent โ†’ First Quarter โ†’ Waxing Gibbous โ†’ Full Moon โ†’ Waning Gibbous โ†’ Last Quarter โ†’ Waning Crescent โ†’ New Moon. Each phase uses "all off first, then light specific LED groups with appropriate brightness" to simulate realistic moon phase shapes.


Click to expand/collapse Moon Phase Simulation code
000 10 0001 7700    R01 = 7700  High-brightness yellow R
001 10 0002 7700 R02 = 7700 High-brightness yellow G
002 10 0003 0000 R03 = 0000 High-brightness yellow B
003 10 0004 3300 R04 = 3300 Medium-brightness yellow R
004 10 0005 3300 R05 = 3300 Medium-brightness yellow G
005 10 0006 0000 R06 = 0000 Medium-brightness yellow B
006 10 0007 1100 R07 = 1100 Low-brightness yellow R
007 10 0008 1100 R08 = 1100 Low-brightness yellow G
008 10 0009 0000 R09 = 0000 Low-brightness yellow B
009 10 000A 0000 R10 = 0000 Off (black) R
00A 10 000B 0000 R11 = 0000 Off (black) G
00B 10 000C 0000 R12 = 0000 Off (black) B
00C 10 0014 0080 R20 = 0080 Delay duration per phase

--- Phase 0: NEW MOON (020) ---
020 E5 0A01 000C All off
021 02 0020 FF00 Delay

--- Phase 1: WAXING CRESCENT (022) ---
022 E5 0A01 000C All off first
023 E5 0701 0001 LED0 low yellow
024 02 0020 FF00 Delay

--- Phase 2: WAXING CRESCENT (025) ---
025 E5 0A01 000C All off first
026 E5 0401 0002 LED0-LED1 medium yellow
027 02 0020 FF00 Delay

--- Phase 3: FIRST QUARTER (028) ---
028 E5 0A01 000C All off first
029 E5 0101 0003 LED0-LED2 high yellow
02A 02 0020 FF00 Delay

--- Phase 4: WAXING GIBBOUS (02B) ---
02B E5 0A01 000C All off first
02C E5 0101 0005 LED0-LED4 high yellow
02D 02 0020 FF00 Delay

--- Phase 5: WAXING GIBBOUS (02E) ---
02E E5 0A01 000C All off first
02F E5 0101 0006 LED0-LED5 high yellow
030 02 0020 FF00 Delay

--- Phase 6: FULL MOON (031) ---
031 E5 0101 000C All 12 LEDs high yellow
032 02 0020 FF00 Delay

--- Phase 7: WANING GIBBOUS (033) ---
033 E5 0A01 000C All off first
034 E5 0101 0705 LED7-LED11 high yellow
035 02 0020 FF00 Delay

--- Phase 8: WANING GIBBOUS (036) ---
036 E5 0A01 000C All off first
037 E5 0101 0804 LED8-LED11 high yellow
038 02 0020 FF00 Delay

--- Phase 9: LAST QUARTER (039) ---
039 E5 0A01 000C All off first
03A E5 0401 0903 LED9-LED11 medium yellow
03B 02 0020 FF00 Delay

--- Phase 10: WANING CRESCENT (03C) ---
03C E5 0A01 000C All off first
03D E5 0701 0A02 LED10-LED11 low yellow
03E 02 0020 FF00 Delay

--- Phase 11: WANING CRESCENT (03F) ---
03F E5 0A01 000C All off first
040 E5 0701 0B01 LED11 low yellow
041 02 0020 FF00 Delay

--- Loop ---
042 0E 0000 0020 Jump back to 020

Register Initialization (000-00C)โ€‹

LineOpcodeDescription
000FZ 0001 7700R01 = 7700, high-brightness yellow R value
001FZ 0002 7700R02 = 7700, high-brightness yellow G value
002FZ 0003 0000R03 = 0000, high-brightness yellow B value
003FZ 0004 3300R04 = 3300, medium-brightness yellow R value
004FZ 0005 3300R05 = 3300, medium-brightness yellow G value
005FZ 0006 0000R06 = 0000, medium-brightness yellow B value
006FZ 0007 1100R07 = 1100, low-brightness yellow R value
007FZ 0008 1100R08 = 1100, low-brightness yellow G value
008FZ 0009 0000R09 = 0000, low-brightness yellow B value
009FZ 000A 0000R10 = 0000, off (black) R value
00AFZ 000B 0000R11 = 0000, off (black) G value
00BFZ 000C 0000R12 = 0000, off (black) B value
00CFZ 0014 0080R20 = 0080, delay duration per phase

12-Phase Moon Cycle (020-042)โ€‹

Pattern: All-off (E5 0A01) โ†’ Light specific LEDs (E5) โ†’ Delay (YS) โ†’ Next phase

PhaseLinesDescription
0020-021New Moon โ€” all LEDs off
1022-024Waxing Crescent โ€” LED0 low yellow
2025-027Waxing Crescent โ€” LED0-LED1 medium yellow
3028-02AFirst Quarter โ€” LED0-LED2 high yellow
402B-02DWaxing Gibbous โ€” LED0-LED4 high yellow
502E-030Waxing Gibbous โ€” LED0-LED5 high yellow
6031-032Full Moon โ€” all 12 LEDs high yellow
7033-035Waning Gibbous โ€” LED7-LED11 high yellow
8036-038Waning Gibbous โ€” LED8-LED11 high yellow
9039-03BLast Quarter โ€” LED9-LED11 medium yellow
1003C-03EWaning Crescent โ€” LED10-LED11 low yellow
1103F-041Waning Crescent โ€” LED11 low yellow
Loop042ZY 0000 0020 โ€” jump back to 020, infinite cycle

E5 Batch Instruction Referenceโ€‹

ExampleMeaning
E5 0A01 000CSet 12 LEDs starting at LED0 with values from R10-R12 (high bytes): all off
E5 0101 0006Set 6 LEDs starting at LED0 with values from R01-R03 (high bytes): high-brightness yellow
E5 0401 0903Set 3 LEDs starting at LED9 with values from R04-R06 (high bytes): medium-brightness yellow
E5 0701 0B01Set 1 LED starting at LED11 with values from R07-R09 (high bytes): low-brightness yellow


12-LED Ring Clock (Hour Gradient + Minute PWM + Seconds Digital Output + PWM Fade)โ€‹

Hardware: 12 WS2812B LEDs arranged in a circle (positions 00-0B, clockwise). LED00 = 12 o'clock, LED01 = 1 o'clock, ... LED0B = 11 o'clock. 4 additional mono-color LEDs on IO[7:4] for seconds sub-display. 4 PWM channels (R2A-R2D, range 0000-03E8) for minute/second smooth fade.

Display Logic:

  • Hour Hand (Green): State range 0-71 (12 positions ร— 6 brightness levels). Position = state/6, sub-level = state%6. Uses E4 instruction to set green channel: leaving LED fades from L5โ†’L0, entering LED fades from L0โ†’L5, creating a smooth gradient between two adjacent hour positions.
  • Minute Hand (Blue): State range 0-59. Position = state/5 (which of 12 LED positions). Sub-step = state%5 (0-4 intermediate). Uses E4 to set blue channel at position LED (max brightness). Sets R2A-R2D PWM values (0000/0CCC/1999/2666/03E8) proportional to sub-step for smooth minute transition indication.
  • Second Hand (Red): State range 0-59. Position = state/5. Sub-step = state%5. Uses E4 to set red channel at position LED. Sets digital output on IO[7:4] (00/01/03/07/0F) = 0/1/2/3/4 mono LEDs lit. Also uses PWM fade on the "just-lit" LED (value 0000โ†’03E8 proportional to sub-step) to create a visual fade-in effect.

Core Opcodes: 10 (FZ) init ยท 2D register divide by literal ยท 2E register mod literal ยท 11 register copy ยท E4 single LED RGB ยท 0x04/0x05 conditional jump ยท 0x0E unconditional jump ยท 0x02 delay ยท 0x13 registerโ†’digital port

Register Plan:

RegisterPurpose
R00Temporary / working register
R01Brightness L0 = 0000
R02Brightness L1 = 1100
R03Brightness L2 = 3300
R04Brightness L3 = 5500
R05Brightness L4 = 7700
R06Brightness L5 = 9900
R07Hour hand state (00-47)
R08Minute hand state (00-3B)
R09Second hand state (00-3B)
R0ADivisor 6 (for hour)
R0BDivisor 5 (for minute/second)
R0CTemporary value (hour position)
R0DTemporary value (minute position)
R0ETemporary value (second position)
R0FTemporary value (brightness index)
R10LED RGB value buffer
R20Delay duration (03E8 = 1 second)
R2APWM channel A output (minute)
R2BPWM channel B output (minute)
R2CPWM channel C output (minute fade)
R2DPWM channel D output (second fade)

Time Initialization Example (10:30:45):

  • Hour state = (10 ร— 6) + (30 / 12) = 60 + 2 = 3C hex... but simpler: directly set R07 = computed value. Hour position advances by 1 every 12 minutes (720s / 12 positions = 60s per state, but 6 brightness levels per position โ†’ 10s per level). So hour state = (hour ร— 6) + (minutes / 12). For 10:30: (10ร—6)+2 = 62 = 3E.
  • Minute state = 30 = 1E. Position 6 (LED06), sub-step 0.
  • Second state = 45 = 2D. Position 9 (LED09), sub-step 0.

Click to expand/collapse 12-LED Ring Clock code
========== Register Initialization (000-023) ==========
000 FZ 0001 0000 R01 = 0000 Brightness L0 (off)
001 FZ 0002 1100 R02 = 1100 Brightness L1
002 FZ 0003 3300 R03 = 3300 Brightness L2
003 FZ 0004 5500 R04 = 5500 Brightness L3
004 FZ 0005 7700 R05 = 7700 Brightness L4
005 FZ 0006 9900 R06 = 9900 Brightness L5 (max)
006 FZ 000A 0006 R0A = 0006 Hour divisor = 6
007 FZ 000B 0005 R0B = 0005 Minute/second divisor = 5
008 FZ 0020 03E8 R20 = 03E8 Delay = 1 second per tick

========== TIME INITIALIZATION (009-00B) ==========
009 FZ 0007 003E R07 = 003E Hour state = 62 (10:30, position 10, level 2)
00A FZ 0008 001E R08 = 001E Minute state = 30 (position 6, sub-step 0)
00B FZ 0009 002D R09 = 002D Second state = 45 (position 9, sub-step 0)

========== Main Loop (010-023): Update โ†’ Render โ†’ Delay โ†’ Loop ==========
010 FZ 0000 003B R00 = 003B Compare value for overflow check (59)
011 04 0009 0015 If R09 > 59: minute rollover, jump to minute increment
012 12 0009 0001 R09 += 1 Increment second state
013 DY 0030 0000 Call Hour Render
014 DY 0070 0000 Call Minute Render
015 DY 00B0 0000 Call Second Render
016 02 0020 FF00 Delay 1 second (use R20 as duration reference)
017 ZY 0000 0010 Jump back to 010, loop forever

--- Minute rollover handling (018-023) ---
018 FZ 0009 0000 R09 = 0000 Reset second state to 0
019 04 0008 0022 If R08 > 59: hour rollover, jump to hour increment
01A 12 0008 0001 R08 += 1 Increment minute state
01B 04 0007 0026 If R07 > 71: hour overflow, jump to hour reset
01C DY 0030 0000 Call Hour Render
01D DY 0070 0000 Call Minute Render
01E DY 00B0 0000 Call Second Render
01F 02 0020 FF00 Delay 1 second
020 ZY 0000 0010 Jump back to main loop

--- Hour rollover handling (021-023) ---
021 FZ 0008 0000 R08 = 0000 Reset minute state to 0
022 12 0007 0001 R07 += 1 Increment hour state
023 04 0007 0047 If R07 > 71: overflow reset
024 ZY 0000 001C Continue rendering at 01C
025 FZ 0007 0000 R07 = 0000 Reset hour to 0
026 ZY 0000 001C Continue rendering at 01C

========== Hour Hand Render (030-06F): Green gradient ==========
030 FZ 000C 0000 R0C = 0 Clear hour position
031 11 0000 0007 R00 = R07 Copy hour state to R00 for division
032 2D 0000 0006 R00 = R00/6 Get hour position (0-11) โ†’ R00
033 11 000C 0000 R0C = R00 Save hour position to R0C

034 11 0000 0007 R00 = R07 Copy hour state for mod
035 2E 0000 0006 R00 = R00%6 Get brightness index (0-5)
036 11 000F 0000 R0F = R00 Save brightness index to R0F

037 06 0000 004A If R0F = 0: exact position, jump to bright-only mode
038 06 0001 004C If R0F = 1: jump to level 1 handler
039 06 0002 004E If R0F = 2: jump to level 2 handler
03A 06 0003 0050 If R0F = 3: jump to level 3 handler
03B 06 0004 0052 If R0F = 4: jump to level 4 handler
03C 06 0005 0054 If R0F = 5: jump to level 5 handler
03D ZY 0000 006E Fallback: return

--- Brightness level dispatch table (index 0 โ†’ leaving LED L5, entering LED L0) ---
03E (not used, handled above)

--- Calculate leaving LED position = R0C (current position) ---
--- Calculate entering LED position = (R0C + 1) mod 12 ---
03F 12 000C 0001 R0C += 1 R0C = next position candidate
040 FZ 0000 000B R00 = 000B Compare with 11 (max valid position)
041 05 000C 0044 If R0C < 12 (R0C โ‰ค 11): positions valid, skip reset
042 FZ 000C 0000 R0C = 0 Reset entering position to 0
043 ZY 0000 0044 Continue

--- Now: R0C = entering position, leaving position = R0C - 1 stored in R0D ---
044 11 000D 000C R0D = R0C Backup entering position
045 12 000D 000B R0D = R0D + 11 ( = R0C - 1, overflow safe) โ†’ actually need subtract
046 2B 000D 0001 R0D = R0D - 1 R0D = leaving position = entering - 1
047 05 000D 0049 If R0D < 12 (valid): skip wrap check
048 FZ 000D 000B R0D = 0B Wrap: leaving = position 11
049 ZY 0000 004A Continue to brightness dispatch

--- Brightness dispatch: R0F (0-5) determines leaving LED level L5-R0F and entering LED level R0F ---
04A FZ 0000 0000 [Level 0] leaving L5, entering L0 (exact position)
04B 11 0010 0006 R10 = R06 L5 for leaving LED
04C E4 0D00 1000 Leaving LED: Green=L5 (R0D=position, high byte = 00, low byte G=R10 high=99)
Note: E4 format is E4 [POS+R] [G+B]. Need rethinking.
04D FZ 0000 0000 placeholder
...

Note: The above E4 instruction format needs reworking. Using simplified direct LED addressing:
E4 format: `E4 [position nibble + R-value high byte] [G-value high byte + B-value high byte]`

Simplifying: Use fixed LED position numbers 00-0B and set RGB with E4 using literal values for each of 12 positions via jump table.

--- Revised Hour Hand Render: Compute position + brightness level, then use jump table (050-06F) ---
050 11 0000 0007 R00 = R07 hour state
051 2D 0000 0006 R00 = R00 / 6 position
052 11 000C 0000 R0C = R00 save position
053 11 0000 0007 R00 = R07
054 2E 0000 0006 R00 = R00 % 6 brightness level (0-5)
055 11 000F 0000 R0F = R00 save level

056 06 000C 0060 If position = 0 โ†’ jump to LED00 handler
057 06 000C 0061 If position = 1 โ†’ jump to LED01 handler
058 06 000C 0062 If position = 2 โ†’ jump to LED02 handler
059 06 000C 0063 If position = 3 โ†’ jump to LED03 handler
05A 06 000C 0064 If position = 4 โ†’ jump to LED04 handler
05B 06 000C 0065 If position = 5 โ†’ jump to LED05 handler
05C 06 000C 0066 If position = 6 โ†’ jump to LED06 handler
05D 06 000C 0067 If position = 7 โ†’ jump to LED07 handler
05E 06 000C 0068 If position = 8 โ†’ jump to LED08 handler
05F 06 000C 0069 If position = 9 โ†’ jump to LED09 handler
060 06 000C 006A If position = 10 โ†’ jump to LED0A handler
061 06 000C 006B If position = 11 โ†’ jump to LED0B handler
062 ZY 0000 006F Fallback return

--- LED position handlers 00-0B: Set leaving+entering LEDs with proper green levels (063-06B) ---
063 11 000D 000C Position-based logic continues...
...

06E 13 0010 0000 Output final value
06F FH 0000 0000 Return from hour render

========== Minute Hand Render (070-0AF): Blue LED + PWM ==========
...
0AF FH 0000 0000 Return from minute render

========== Second Hand Render (0B0-0FF): Red LED + Digital Output + PWM Fade ==========
...
0FF FH 0000 0000 Return from second render

Design Walkthrough & Bug Analysis

Click to expand detailed design explanation

Overall Architectureโ€‹

The clock uses a state-driven render model with three independent hands:

HandRegisterRangeUpdate TriggerRender Subroutine
Hour (green)R070-71 (12 positions ร— 6 brightness steps)Every 60 minutes030-05E
Minute (blue)R080-59 (12 positions ร— 5 sub-steps)Every 60 seconds070-09F
Second (red)R090-59 (12 positions ร— 5 sub-steps)Every 1 second0A0-0CF

Initialization (000-00B): Preload 6 brightness levels into R01-R06, set divisors (R0A=6, R0B=5), set PWM max (R20=03E8), and set initial time (R07=hour, R08=minute, R09=second).

Main Loop (010-026): Check if each hand overflows โ†’ if yes, rollover and cascade to next hand โ†’ call all three render subroutines โ†’ delay 1 second โ†’ loop.

Bug #1: Conditional Jump Instruction Format (CRITICAL)โ€‹

Root cause of the 020-line stuck loop.

The 0x04/0x05/0x06 instructions compare R00 against a literal value, NOT an arbitrary register against R00:

04 [literal] [target]  โ†’  if R00 > literal, jump
05 [literal] [target] โ†’ if R00 < literal, jump
06 [literal] [target] โ†’ if R00 == literal, jump

What the code does (line 010-011):

010  FZ  0000  003B    R00 = 59
011 04 0009 0018 โ†’ if R00(59) > 9: jump to 018 โ† ALWAYS TRUE!

What was intended: "If R09 > 59, jump to rollover"

Correct approach: Copy R09 to R00 first, then compare:

10 0000 003B    R00 = 59 (threshold)
11 0000 0009 R00 = R09 (copy second state to R00)
04 003B 0018 if R00 > 59: jump to rollover

This same error affects ALL conditional jumps in the program (lines 011, 019, 01B, 023, 038, 03D, 040-045, 077-07B, 0A7-0AB).

Bug #2: Wrong Opcodes for Division/Remainder/Subtractionโ€‹

UsedCorrectInstruction
2D1DDivision (R00 = R00 / R[reg])
2E1ERemainder (R00 = R00 % R[reg])
2B12 10Decrement (12 with OP-00=10)

Additionally, 1D/1E operate on two registers, not a register and a literal:

1D 00 [dest] 00 [src]  โ†’  R[dest] = R[dest] / R[src]

So 2D 0000 0006 (intended: R00 = R00 / 6) must be:

1D 00 00 00 0A    R00 = R00 / R0A   (where R0A = 6, preloaded)

Bug #3: E4 LED Position Cannot Use Register Valueโ€‹

The E4 instruction takes a literal LED position in the first byte:

E4 [LED_ID + R] [G + B]  โ†’  set LED #LED_ID to (R, G, B)

Code like E4 0D00 1000 tries to set LED #0D (13), which doesn't exist (only 00-0B). The intent was to use the value stored in R0D as the LED position, but E4 does not support register-indirect addressing.

Workaround: Use a 12-way jump table to dispatch to hardcoded E4 instructions for each position:

06 0000 0050    if R00 == 0: jump to LED00 handler
06 0001 0053 if R00 == 1: jump to LED01 handler
... (12 entries)
050 E4 00XX XXXX hardcoded: LED00, R=R10_high, G=00, B=00
053 E4 01XX XXXX hardcoded: LED01, R=R10_high, G=00, B=00

This requires 12 jump entries + 12 E4 instructions per hand, significantly increasing code size.

Summary of Required Fixesโ€‹

  1. Every conditional jump needs a preceding 11 0000 00XX to copy the target register to R00
  2. Division/remainder opcodes change from 2D/2E to 1D/1E, with register-to-register format
  3. Subtraction changes from 2B to 12 10 (decrement mode)
  4. E4 LED position must be hardcoded via jump table, not register-indirect
  5. Estimated code size after fix: ~200+ lines (approaching the 256-line limit)

Seconds-Only Clock Demo (Step 1: Second Hand Only)โ€‹

This is a simplified sub-project that implements only the second hand of the ring clock. It fixes all bugs found in the full clock version and serves as a stepping stone before adding minute and hour hands.

Hardware: 12 WS2812B LEDs (ring, 00-0B) + 4 mono-color LEDs on IO[7:4]

Behavior:

  • Red second hand moves clockwise, 1 LED position per 5 seconds
  • Position = second / 5 (0-11)
  • Sub-step = second % 5 (0-4): controls 4 mono-color LEDs on IO[7:4]
    • Sub-step 0: all 4 LEDs off (second hand lands exactly on a position)
    • Sub-step 1: 1 LED on (IO4)
    • Sub-step 2: 2 LEDs on (IO4-5)
    • Sub-step 3: 3 LEDs on (IO4-6)
    • Sub-step 4: 4 LEDs on (IO4-7)

Register Map:

RegisterPurposeRange
R00Temp/comparison-
R09Second state0-59
R0BDivisor (5)5
R0CLED position (current)0-11
R0DLED position (previous)0-11, init=255
R0FSub-step0-4
R10Digital output value00/10/30/70/F0

Key Fixes Applied:

  1. All conditional jumps (04/06/09) compare R00 against literal/register โ€” copy target register to R00 first via 11
  2. Division uses 1D (not 2D), remainder uses 1E (not 2E), both register-to-register
  3. LED position hardcoded via 12-way jump table (E4 does not support register-indirect)
  4. Anti-flicker: Track previous position in R0D; only extinguish+re-light LEDs when position changes (every 5s), skip LED update when position unchanged (4 out of 5 seconds)
=== Init (000-002) ===
000 FZ 000B 0005 R0B = 5 (divisor)
001 FZ 0009 0000 R09 = 0 (initial seconds, editable)
002 FZ 000D 00FF R0D = 255 (impossible position, forces first render)

=== Main Loop (010-015) ===
010 FZ 0000 0009 R00 = R09
011 04 003B 0017 If R00 > 59: jump to 017 (reset)
012 DY 0020 0000 Call Second Render subroutine
013 12 0009 0001 R09 += 1
014 YS 03E8 0000 Delay 1 second
015 ZY 0000 0010 Jump back to 010

=== Reset (017-018) ===
017 FZ 0009 0000 R09 = 0
018 ZY 0000 0012 Jump to 012 (render reset value)

=== Second Render Subroutine (020-080) ===
--- Compute position & sub-step (020-025) ---
020 FZ 0000 0009 R00 = R09
021 1D 0000 000B R00 = R00 / R0B (position)
022 FZ 000C 0000 R0C = position
023 FZ 0000 0009 R00 = R09
024 1E 0000 000B R00 = R00 % R0B (sub-step)
025 FZ 000F 0000 R0F = sub-step

--- Anti-flicker: check if position changed (026-027) ---
026 11 0000 000D R00 = R0D (previous position)
027 09 000C 0066 If R00 == R0C: jump to 066 (skip LED update)

--- Position changed: update previous & extinguish all (028-034) ---
028 11 000D 000C R0D = R0C (save new position)
029 CD 0000 0000 LED00 off
02A CD 0100 0000 LED01 off
02B CD 0200 0000 LED02 off
02C CD 0300 0000 LED03 off
02D CD 0400 0000 LED04 off
02E CD 0500 0000 LED05 off
02F CD 0600 0000 LED06 off
030 CD 0700 0000 LED07 off
031 CD 0800 0000 LED08 off
032 CD 0900 0000 LED09 off
033 CD 0A00 0000 LED10 off
034 CD 0B00 0000 LED11 off

--- Position jump table (035-041) ---
035 FZ 0000 000C R00 = R0C (position)
036 06 0000 0042 If pos=0: jump to LED00 handler
037 06 0001 0045 If pos=1: jump to LED01 handler
038 06 0002 0048 If pos=2: jump to LED02 handler
039 06 0003 004B If pos=3: jump to LED03 handler
03A 06 0004 004E If pos=4: jump to LED04 handler
03B 06 0005 0051 If pos=5: jump to LED05 handler
03C 06 0006 0054 If pos=6: jump to LED06 handler
03D 06 0007 0057 If pos=7: jump to LED07 handler
03E 06 0008 005A If pos=8: jump to LED08 handler
03F 06 0009 005D If pos=9: jump to LED09 handler
040 06 000A 0060 If pos=10: jump to LED10 handler
041 06 000B 0063 If pos=11: jump to LED11 handler

--- 12 position handlers (3 lines each: set LED + load sub-step + jump) ---
042 CD 0099 0000 LED00 = red (R=99)
043 FZ 0000 000F R00 = sub-step
044 ZY 0000 0067 Jump to digital output

045 CD 0199 0000 LED01 = red
046 FZ 0000 000F
047 ZY 0000 0067

048 CD 0299 0000 LED02 = red
049 FZ 0000 000F
04A ZY 0000 0067

04B CD 0399 0000 LED03 = red
04C FZ 0000 000F
04D ZY 0000 0067

04E CD 0499 0000 LED04 = red
04F FZ 0000 000F
050 ZY 0000 0067

051 CD 0599 0000 LED05 = red
052 FZ 0000 000F
053 ZY 0000 0067

054 CD 0699 0000 LED06 = red
055 FZ 0000 000F
056 ZY 0000 0067

057 CD 0799 0000 LED07 = red
058 FZ 0000 000F
059 ZY 0000 0067

05A CD 0899 0000 LED08 = red
05B FZ 0000 000F
05C ZY 0000 0067

05D CD 0999 0000 LED09 = red
05E FZ 0000 000F
05F ZY 0000 0067

060 CD 0A99 0000 LED10 = red
061 FZ 0000 000F
062 ZY 0000 0067

063 CD 0B99 0000 LED11 = red
064 FZ 0000 000F
065 ZY 0000 0067

--- Sub-step digital output (066-080) ---
066 FZ 0000 000F R00 = sub-step (reached when position unchanged)
067 06 0000 0076 If sub=0: all off
068 06 0001 0078 If sub=1: 1 LED on
069 06 0002 007A If sub=2: 2 LEDs on
06A 06 0003 007C If sub=3: 3 LEDs on
06B 06 0004 007E If sub=4: 4 LEDs on
06C ZY 0000 007F Default (should not reach)

076 FZ 0010 0000 R10 = 00 (all off)
077 ZY 0000 007F
078 FZ 0010 0010 R10 = 10 (IO4 on)
079 ZY 0000 007F
07A FZ 0010 0030 R10 = 30 (IO4-5 on)
07B ZY 0000 007F
07C FZ 0010 0070 R10 = 70 (IO4-6 on)
07D ZY 0000 007F
07E FZ 0010 00F0 R10 = F0 (IO4-7 all on)

07F SC 0010 0000 Output R10 to digital port
080 FH 0000 0000 Return

Code size: 99 instruction lines (well within 256-line limit)

Anti-flicker mechanism: R0D tracks the previous LED position. On each render:

  • If position unchanged (4 out of 5 seconds): jump directly to digital output (line 066), skip LED extinguish+re-light
  • If position changed (every 5 seconds): extinguish all LEDs, light new position, update R0D

To set initial time: Modify line 001 to change R09 initial value (0-59). Example: 001 10 0009 002D sets seconds to 45.


Mode-Switching Clock Demo (Step 2: Second / Minute / Hour Toggle)โ€‹

See the Step 1 section above for the basic anti-flicker second hand pattern. This mode-switching version extends it by adding:

  • Button (R3F): Pressing cycles R14 through 0 (seconds) โ†’ 1 (minutes) โ†’ 2 (hours) โ†’ 0
  • R13 release flag: Prevents repeated toggles while button is held
  • R0D reset on mode change: Forces LED redraw with new color on mode switch
  • Three render subroutines: Same anti-flicker structure, red for seconds, green for minutes, blue for hours
  • Continuous counting: R09 (sec), R0A (min), R0B (hour) all increment in background regardless of display mode

Button detection flow:

R3F==0 โ†’ set R13=0 (ready for press)
R3F==1 AND R13==0 โ†’ R14 += 1, if R14==3 reset to 0, set R13=1, set R0D=255 (force redraw)
R3F==1 AND R13==1 โ†’ do nothing (already handled)

Color selection:

If R14==0 โ†’ call red render (R09 for position/sub-step, LED color: red)
If R14==1 โ†’ call green render (R0A for position/sub-step, LED color: green)
If R14==2 โ†’ call blue render (R0B for position, minutes/12 for sub-step, LED color: blue)

Hour hand special handling: Hours are 0-11 (no /5 division needed for position). Sub-step is derived from minutes: 0-11min=sub0, 12-23min=sub1, 24-35min=sub2, 36-47min=sub3, 48-59min=sub4.

Register Map:

RegisterPurpose
R00Temporary/comparison
R09Seconds (0-59)
R0AMinutes (0-59)
R0BHours (0-11)
R0CCurrent LED position (0-11)
R0DPrevious position (anti-flicker)
R0FSub-step (0-4)
R10Digital IO output value
R13Button release flag
R14Display mode (0=sec, 1=min, 2=hour)

Total line usage: ~384 lines (well under 512 limit)


Complete Instruction Code (Main Loop)โ€‹

000 10 000B 0005    R0B = 5 (divisor for sec/min position calc)
001 10 0009 0000 R09 = 0 (seconds)
002 10 000A 0000 R0A = 0 (minutes)
003 10 000D 00FF R0D = 255 (prev position, force initial redraw)
004 10 0014 0000 R14 = 0 (mode: seconds display)
005 10 0013 0000 R13 = 0 (button release flag)

=== Button Detection (010-01F): Cycle mode 0โ†’1โ†’2โ†’0 ===
010 11 0000 003F R00 = R3F (button state)
011 09 0001 0014 If R00==1: jump to 014 (button is pressed)
012 10 0013 0000 R13 = 0 (button released, reset flag)
013 0E 0000 0020 Jump to mode select
014 11 0000 0013 R00 = R13 (check release flag)
015 09 0000 0017 If R00==0: jump to 017 (toggle mode now)
016 0E 0000 0020 Jump to mode select (already handled this press)
017 12 0014 0001 R14 += 1 (advance to next mode)
018 11 0000 0014 R00 = R14 (check if mode==3)
019 09 0003 001B If R00==3: jump to 01B (reset mode to 0)
01A 0E 0000 001C Jump to set release flag
01B 10 0014 0000 R14 = 0 (reset to mode 0)
01C 10 0013 0001 R13 = 1 (set release flag, prevent repeat)
01D 10 000D 00FF R0D = 255 (force LED redraw for new color)

=== Mode Select (020-02F): Route to correct color renderer ===
020 11 0000 0014 R00 = R14
021 09 0001 0026 If R00==1: jump to green (minutes)
022 09 0002 0029 If R00==2: jump to blue (hours)
--- Mode 0: Red Seconds ---
023 11 0000 0009 R00 = R09 (seconds for bounds check)
024 04 003B 002B If R00>59: skip (shouldn't happen)
025 0C 0040 0000 Call red seconds render (040)
026 0E 0000 0030 Jump to counting
--- Mode 1: Green Minutes ---
027 11 0000 000A R00 = R0A (minutes for bounds check)
028 0C 00A0 0000 Call green minutes render (0A0)
029 0E 0000 0030 Jump to counting
--- Mode 2: Blue Hours ---
02A 0C 0100 0000 Call blue hours render (100)
02B 0E 0000 0030 Jump to counting

=== Counting (030-03F): Advance time ===
030 12 0009 0001 Seconds += 1
031 11 0000 0009 R00 = R09
032 09 003C 0034 If R00==60: jump to minute increment
033 0E 0000 0038 Jump to delay
034 10 0009 0000 R09 = 0 (reset seconds)
035 12 000A 0001 Minutes += 1
036 11 0000 000A R00 = R0A
037 09 003C 0039 If R00==60: jump to hour increment
038 02 03E8 0000 Delay 1 second
039 0E 0000 0010 Loop back to button detection
03A 10 000A 0000 R0A = 0 (reset minutes)
03B 12 000B 0001 Hours += 1
03C 11 0000 000B R00 = R0B
03D 09 000C 003F If R00==12: jump to reset hours
03E 02 03E8 0000 Delay 1 second
03F 0E 0000 0010 Loop back
040 10 000B 0000 R0B = 0 (reset hours)
041 02 03E8 0000 Delay 1 second
042 0E 0000 0010 Loop back

Red seconds render subroutine (050-0B7): Uses R09/5 for position, R09%5 for sub-step. LED color = red (E4 xx99 0000).

Green minutes render subroutine (0C0-127): Uses R0A/5 for position, R0A%5 for sub-step. LED color = green (E4 0000 9900).

Blue hours render subroutine (130-197): Position = R0B directly (0-11, no /5 needed). Sub-step derived from minutes by comparing R0A against 12/24/36/48 thresholds. LED color = blue (E4 0000 0099).


Five-Color Running Light (12-Position LED)โ€‹

12 WS2812B LEDs arranged in a circle, displaying a five-color running light effect in sequence. Each color lights LEDs one by one from LED00 to LED0B, holds briefly after all are lit, then extinguishes all and proceeds to the next color. Color order: White โ†’ Red โ†’ Yellow โ†’ Green โ†’ Blue. Each color component max is 0x33 to ensure not too bright.

Core Opcodes: FZ (10) init ยท CD (E4) light/extinguish LED ยท YS (02) delay ยท DY (0C) call subroutine ยท FH (0D) return ยท ZY (0E) unconditional jump

Color Parameters (CD instruction format: CD LED_ID+R G+B):

ColorRGBCD Example (LED00)
White333333CD 0033 3333
Red330000CD 0033 0000
Yellow333300CD 0033 3300
Green003300CD 0000 3300
Blue000033CD 0000 0033
Off000000CD 0000 0000

Click to expand/collapse Five-Color Running Light code
000 10 0001 0000
001 10 0002 0001
010 0C 0020 0000
011 0C 0040 0000
012 0C 0060 0000
013 0C 0080 0000
014 0C 00A0 0000
015 0E 0000 0010
020 E4 0033 3333
021 02 0080 0000
022 E4 0133 3333
023 02 0080 0000
024 E4 0233 3333
025 02 0080 0000
026 E4 0333 3333
027 02 0080 0000
028 E4 0433 3333
029 02 0080 0000
02A E4 0533 3333
02B 02 0080 0000
02C E4 0633 3333
02D 02 0080 0000
02E E4 0733 3333
02F 02 0080 0000
030 E4 0833 3333
031 02 0080 0000
032 E4 0933 3333
033 02 0080 0000
034 E4 0A33 3333
035 02 0080 0000
036 E4 0B33 3333
037 02 0200 0000
038 0C 00C0 0000
039 0D 0000 0000
040 E4 0033 0000
041 02 0080 0000
042 E4 0133 0000
043 02 0080 0000
044 E4 0233 0000
045 02 0080 0000
046 E4 0333 0000
047 02 0080 0000
048 E4 0433 0000
049 02 0080 0000
04A E4 0533 0000
04B 02 0080 0000
04C E4 0633 0000
04D 02 0080 0000
04E E4 0733 0000
04F 02 0080 0000
050 E4 0833 0000
051 02 0080 0000
052 E4 0933 0000
053 02 0080 0000
054 E4 0A33 0000
055 02 0080 0000
056 E4 0B33 0000
057 02 0200 0000
058 0C 00C0 0000
059 0D 0000 0000
060 E4 0033 3300
061 02 0080 0000
062 E4 0133 3300
063 02 0080 0000
064 E4 0233 3300
065 02 0080 0000
066 E4 0333 3300
067 02 0080 0000
068 E4 0433 3300
069 02 0080 0000
06A E4 0533 3300
06B 02 0080 0000
06C E4 0633 3300
06D 02 0080 0000
06E E4 0733 3300
06F 02 0080 0000
070 E4 0833 3300
071 02 0080 0000
072 E4 0933 3300
073 02 0080 0000
074 E4 0A33 3300
075 02 0080 0000
076 E4 0B33 3300
077 02 0200 0000
078 0C 00C0 0000
079 0D 0000 0000
080 E4 0000 3300
081 02 0080 0000
082 E4 0100 3300
083 02 0080 0000
084 E4 0200 3300
085 02 0080 0000
086 E4 0300 3300
087 02 0080 0000
088 E4 0400 3300
089 02 0080 0000
08A E4 0500 3300
08B 02 0080 0000
08C E4 0600 3300
08D 02 0080 0000
08E E4 0700 3300
08F 02 0080 0000
090 E4 0800 3300
091 02 0080 0000
092 E4 0900 3300
093 02 0080 0000
094 E4 0A00 3300
095 02 0080 0000
096 E4 0B00 3300
097 02 0200 0000
098 0C 00C0 0000
099 0D 0000 0000
0A0 E4 0000 0033
0A1 02 0080 0000
0A2 E4 0100 0033
0A3 02 0080 0000
0A4 E4 0200 0033
0A5 02 0080 0000
0A6 E4 0300 0033
0A7 02 0080 0000
0A8 E4 0400 0033
0A9 02 0080 0000
0AA E4 0500 0033
0AB 02 0080 0000
0AC E4 0600 0033
0AD 02 0080 0000
0AE E4 0700 0033
0AF 02 0080 0000
0B0 E4 0800 0033
0B1 02 0080 0000
0B2 E4 0900 0033
0B3 02 0080 0000
0B4 E4 0A00 0033
0B5 02 0080 0000
0B6 E4 0B00 0033
0B7 02 0200 0000
0B8 0C 00C0 0000
0B9 0D 0000 0000
0C0 E4 0000 0000
0C1 E4 0100 0000
0C2 E4 0200 0000
0C3 E4 0300 0000
0C4 E4 0400 0000
0C5 E4 0500 0000
0C6 E4 0600 0000
0C7 E4 0700 0000
0C8 E4 0800 0000
0C9 E4 0900 0000
0CA E4 0A00 0000
0CB E4 0B00 0000
0CC 0D 0000 0000

Register Initialization (000-001)โ€‹

LineOpcodeDescription
000FZ 0001 0000R01 = 0, constant
001FZ 0002 0001R02 = 1, constant

Main Loop (010-015)โ€‹

LineOpcodeDescription
010DY 0020 0000Call white running subroutine at 020
011DY 0040 0000Call red running subroutine at 040
012DY 0060 0000Call yellow running subroutine at 060
013DY 0080 0000Call green running subroutine at 080
014DY 00A0 0000Call blue running subroutine at 0A0
015ZY 0000 0010Jump back to 010, infinite loop

White Running (020-039)โ€‹

LineOpcodeDescription
020CD 0033 3333LED00 white (R=33, G=33, B=33)
021YS 0080 0000Delay for visible running effect
022-036CD LED33 3333 + YSLED01-LED0B lit white one by one, each with delay
037YS 0200 0000Hold after all 12 LEDs lit
038DY 00C0 0000Call all-off subroutine at 0C0
039FH 0000 0000White running complete, return

Red Running (040-059)โ€‹

LineOpcodeDescription
040CD 0033 0000LED00 red (R=33, G=00, B=00)
041YS 0080 0000Delay
042-056CD LED33 0000 + YSLED01-LED0B lit red one by one, each with delay
057YS 0200 0000Hold after all lit
058DY 00C0 0000Call all-off subroutine
059FH 0000 0000Return

Yellow Running (060-079)โ€‹

LineOpcodeDescription
060CD 0033 3300LED00 yellow (R=33, G=33, B=00)
061YS 0080 0000Delay
062-076CD LED33 3300 + YSLED01-LED0B lit yellow one by one, each with delay
077YS 0200 0000Hold after all lit
078DY 00C0 0000Call all-off subroutine
079FH 0000 0000Return

Green Running (080-099)โ€‹

LineOpcodeDescription
080CD 0000 3300LED00 green (R=00, G=33, B=00)
081YS 0080 0000Delay
082-096CD LED00 3300 + YSLED01-LED0B lit green one by one, each with delay
097YS 0200 0000Hold after all lit
098DY 00C0 0000Call all-off subroutine
099FH 0000 0000Return

Blue Running (0A0-0B9)โ€‹

LineOpcodeDescription
0A0CD 0000 0033LED00 blue (R=00, G=00, B=33)
0A1YS 0080 0000Delay
0A2-0B6CD LED00 0033 + YSLED01-LED0B lit blue one by one, each with delay
0B7YS 0200 0000Hold after all lit
0B8DY 00C0 0000Call all-off subroutine
0B9FH 0000 0000Return

All-Off Subroutine (0C0-0CC)โ€‹

LineOpcodeDescription
0C0CD 0000 0000LED00 off
0C1CD 0100 0000LED01 off
0C2CD 0200 0000LED02 off
0C3CD 0300 0000LED03 off
0C4CD 0400 0000LED04 off
0C5CD 0500 0000LED05 off
0C6CD 0600 0000LED06 off
0C7CD 0700 0000LED07 off
0C8CD 0800 0000LED08 off
0C9CD 0900 0000LED09 off
0CACD 0A00 0000LED0A off
0CBCD 0B00 0000LED0B off
0CCFH 0000 0000All-off complete, return

Five-Color Flowing Lights (E5 Instruction Optimized Version)โ€‹

Turning off all LEDs with a single E5 instruction: This example builds on the original five-color flowing lights by replacing the 12 individual LED-off instructions with a single E5 instruction. E4 instructions are still used to light up individual LEDs for the flowing effect, while the E5 instruction uses RGB values stored in registers to set multiple LEDs at once โ€” reducing the turn-off operation from 12 instructions to just 1.

Core Instructions: FZ (10) Initialize Registers ยท E4 Set Single LED Color ยท E5 Batch Set LED Colors via Registers ยท YS (02) Delay ยท DY (0C) Call Subroutine ยท FH (0D) Return ยท ZY (0E) Unconditional Jump

E5 Instruction Reference:

ParameterValueDescription
OP0003Starting register number (uses R03, R04, R05)
OP010100 = use low byte, 01 = use high byte
OP1000Starting LED number
OP110CNumber of LEDs (0C = 12)

Format: E5 OP00+OP01 OP10+OP11 โ†’ example: E5 0301 000C (uses R03-R05 high bytes, sets LED00-LED11)

Register Plan:

RegistersPurpose
R00-R02Current color values (updated at runtime)
R03-R05All-zero values (used for turning LEDs off)

Click to expand/collapse E5 Optimized Version Full Code
000 10 0000 0000
001 10 0001 0000
002 10 0002 0000
003 10 0003 0000
004 10 0004 0000
005 10 0005 0000
010 0C 0020 0000
011 0C 0040 0000
012 0C 0060 0000
013 0C 0080 0000
014 0C 00A0 0000
015 0E 0000 0010
020 10 0000 3333
021 10 0001 3333
022 10 0002 3333
023 E4 0033 3333
024 02 0080 0000
025 E4 0133 3333
026 02 0080 0000
027 E4 0233 3333
028 02 0080 0000
029 E4 0333 3333
02A 02 0080 0000
02B E4 0433 3333
02C 02 0080 0000
02D E4 0533 3333
02E 02 0080 0000
02F E4 0633 3333
030 02 0080 0000
031 E4 0733 3333
032 02 0080 0000
033 E4 0833 3333
034 02 0080 0000
035 E4 0933 3333
036 02 0080 0000
037 E4 0A33 3333
038 02 0080 0000
039 E4 0B33 3333
03A 02 0200 0000
03B E5 0301 000C
03C 02 0080 0000
03D 0D 0000 0000
040 10 0000 3300
041 10 0001 0000
042 10 0002 0000
043 E4 0033 0000
044 02 0080 0000
045 E4 0133 0000
046 02 0080 0000
047 E4 0233 0000
048 02 0080 0000
049 E4 0333 0000
04A 02 0080 0000
04B E4 0433 0000
04C 02 0080 0000
04D E4 0533 0000
04E 02 0080 0000
04F E4 0633 0000
050 02 0080 0000
051 E4 0733 0000
052 02 0080 0000
053 E4 0833 0000
054 02 0080 0000
055 E4 0933 0000
056 02 0080 0000
057 E4 0A33 0000
058 02 0080 0000
059 E4 0B33 0000
05A 02 0200 0000
05B E5 0301 000C
05C 02 0080 0000
05D 0D 0000 0000
060 10 0000 3300
061 10 0001 3300
062 10 0002 0000
063 E4 0033 3300
064 02 0080 0000
065 E4 0133 3300
066 02 0080 0000
067 E4 0233 3300
068 02 0080 0000
069 E4 0333 3300
06A 02 0080 0000
06B E4 0433 3300
06C 02 0080 0000
06D E4 0533 3300
06E 02 0080 0000
06F E4 0633 3300
070 02 0080 0000
071 E4 0733 3300
072 02 0080 0000
073 E4 0833 3300
074 02 0080 0000
075 E4 0933 3300
076 02 0080 0000
077 E4 0A33 3300
078 02 0080 0000
079 E4 0B33 3300
07A 02 0200 0000
07B E5 0301 000C
07C 02 0080 0000
07D 0D 0000 0000
080 10 0000 0000
081 10 0001 3300
082 10 0002 0000
083 E4 0000 3300
084 02 0080 0000
085 E4 0100 3300
086 02 0080 0000
087 E4 0200 3300
088 02 0080 0000
089 E4 0300 3300
08A 02 0080 0000
08B E4 0400 3300
08C 02 0080 0000
08D E4 0500 3300
08E 02 0080 0000
08F E4 0600 3300
090 02 0080 0000
091 E4 0700 3300
092 02 0080 0000
093 E4 0800 3300
094 02 0080 0000
095 E4 0900 3300
096 02 0080 0000
097 E4 0A00 3300
098 02 0080 0000
099 E4 0B00 3300
09A 02 0200 0000
09B E5 0301 000C
09C 02 0080 0000
09D 0D 0000 0000
0A0 10 0000 0000
0A1 10 0001 0000
0A2 10 0002 3300
0A3 E4 0000 0033
0A4 02 0080 0000
0A5 E4 0100 0033
0A6 02 0080 0000
0A7 E4 0200 0033
0A8 02 0080 0000
0A9 E4 0300 0033
0AA 02 0080 0000
0AB E4 0400 0033
0AC 02 0080 0000
0AD E4 0500 0033
0AE 02 0080 0000
0AF E4 0600 0033
0B0 02 0080 0000
0B1 E4 0700 0033
0B2 02 0080 0000
0B3 E4 0800 0033
0B4 02 0080 0000
0B5 E4 0900 0033
0B6 02 0080 0000
0B7 E4 0A00 0033
0B8 02 0080 0000
0B9 E4 0B00 0033
0BA 02 0200 0000
0BB E5 0301 000C
0BC 02 0080 0000
0BD 0D 0000 0000

Register Initialization (000-005)โ€‹

LineInstructionDescription
000FZ 0000 0000R00 = 0000, Color R placeholder (updated at start of each subroutine)
001FZ 0001 0000R01 = 0000, Color G placeholder
002FZ 0002 0000R02 = 0000, Color B placeholder
003FZ 0003 0000R03 = 0000, Off R value (fixed=00)
004FZ 0004 0000R04 = 0000, Off G value (fixed=00)
005FZ 0005 0000R05 = 0000, Off B value (fixed=00)

Main Loop (010-015)โ€‹

LineInstructionDescription
010DY 0020 0000Call White flowing subroutine
011DY 0040 0000Call Red flowing subroutine
012DY 0060 0000Call Yellow flowing subroutine
013DY 0080 0000Call Green flowing subroutine
014DY 00A0 0000Call Blue flowing subroutine
015ZY 0000 0010Jump back to 010, infinite loop

Optimization Comparison: E5 Batch Off vs E4 Individual Offโ€‹

MethodInstruction CountExample
E4 Individual Off (Original)12 instructionsE4 0000 0000 โ†’ E4 0100 0000 โ†’ ... โ†’ E4 0B00 0000
E5 Batch Off (Optimized)1 instructionE5 0301 000C

E5 Instruction Parameter Breakdownโ€‹

Taking E5 0301 000C as example:

PartValueMeaning
OP00 (first half of high byte)03Uses R03 as starting register
OP01 (second half of high byte)01Uses high byte of each register for color values
OP10 (first half of low byte)00Starts from LED00
OP11 (second half of low byte)0CTotal 12 LEDs (0C=12)

Color source: High byte of R03=00, R04=00, R05=00 โ†’ RGB=(00,00,00) Black/off.


E5 Rotating LED Effect (Progressive On/Off)โ€‹

Core Idea: Keep E5 instruction's OP10 (starting LED position) fixed at 00, and continuously change OP11 (LED count) to achieve two phases:

  1. Phase 1 (Waxing): E5 0101 00NN โ€” light up N white LEDs from LED0, progressively expanding from 1 to 12 (progressive ON)
  2. Phase 2 (Waning): E5 0401 00NN โ€” overwrite with N black LEDs from LED0, progressively expanding from 0 to 12 (progressive OFF via black overwriting)

Meanwhile, use R20 register to store delay duration, and reference the register value through YS 0020 FF00 format delay instructions, enabling runtime-adjustable speed control.

Key Difference from Snake: The snake moves by changing OP10 (start position) with fixed OP11. This example keeps OP10 fixed at 00 and changes OP11 (count) โ€” the "rotating" effect emerges from progressively lighting and blacking out LEDs from the same origin.

E5 Instruction Parameter Changes (Rotating Version):

PhaseOP00OP01OP10OP11 RangeColor SourceEffect
Progressive ON01010001โ†’0CR01,R02,R03 high byte (white)Light up 1โ†’12 LEDs from LED0
Progressive OFF04010000โ†’0CR04,R05,R06 high byte (black)Overwrite 0โ†’12 LEDs with black

Register Plan:

RegisterValuePurpose
R200008Delay duration = 8ms (very fast flow, modifiable)
R011000White R value (high 8 bits = 10, dim white)
R021000White G value (high 8 bits = 10)
R031000White B value (high 8 bits = 10)
R040000Black R value (high 8 bits = 00, off)
R050000Black G value (high 8 bits = 00, off)
R060000Black B value (high 8 bits = 00, off)

Click to expand/collapse Rotating LED Effect Full Code
000 10 0020 0008
001 10 0001 1000
002 10 0002 1000
003 10 0003 1000
004 10 0004 0000
005 10 0005 0000
006 10 0006 0000
010 E5 0101 0001
011 02 0020 FF00
012 E5 0101 0002
013 02 0020 FF00
014 E5 0101 0003
015 02 0020 FF00
016 E5 0101 0004
017 02 0020 FF00
018 E5 0101 0005
019 02 0020 FF00
01A E5 0101 0006
01B 02 0020 FF00
01C E5 0101 0007
01D 02 0020 FF00
01E E5 0101 0008
01F 02 0020 FF00
020 E5 0101 0009
021 02 0020 FF00
022 E5 0101 000A
023 02 0020 FF00
024 E5 0101 000B
025 02 0020 FF00
026 E5 0101 000C
027 02 0020 FF00
029 E5 0401 0000
02A 02 0020 FF00
02B E5 0401 0001
02C 02 0020 FF00
02D E5 0401 0002
02E 02 0020 FF00
02F E5 0401 0003
030 02 0020 FF00
031 E5 0401 0004
032 02 0020 FF00
033 E5 0401 0005
034 02 0020 FF00
035 E5 0401 0006
036 02 0020 FF00
037 E5 0401 0007
038 02 0020 FF00
039 E5 0401 0008
03A 02 0020 FF00
03B E5 0401 0009
03C 02 0020 FF00
03D E5 0401 000A
03E 02 0020 FF00
03F E5 0401 000B
040 02 0020 FF00
041 E5 0401 000C
042 02 0020 FF00
043 0E 0000 0010

Instruction Notesโ€‹

The core pattern uses two different register color sources to build the rotation effect:

Instruction GroupPurpose
E5 0101 00NNUsing R01-R03 (dim white) as color, light up N LEDs starting from LED0
E5 0401 00NNUsing R04-R06 (black/off) as color, overwrite N LEDs starting from LED0
YS 0020 FF00Read delay from R20 (8ms), controls rotation speed

Visual Effect: The first half (010โ€“027) "grows" a white light bar from left to right across all 12 LEDs. The second half (029โ€“042) then "erases" it from the left using black overwrites โ€” creating a clean wipe-style rotating flow.

E5 Instruction Parameter Comparison Table (Rotating Version)โ€‹

PhaseLinesOP00OP01OP10OP11 RangeColorEffect
Waxing (ON)010โ€“02601010001โ†’0CWhite (R01-R03)1โ†’12 LEDs progressive ON from left
Waning (OFF)029โ€“04104010000โ†’0CBlack (R04-R06)0โ†’12 LEDs progressive black overwrite from left

Register-based Delay + E5 Waterfall Light (Changing OP11 Count, R20 Stores Duration)โ€‹

Core Idea: Keep E5 instruction's OP10 (starting LED position) fixed at 00, and continuously change OP11 (LED count) to achieve sequential lighting on and off from left to right. Meanwhile, use R20 register to store delay duration, and reference the register value through YS 0020 FF00 format delay instructions, enabling runtime-adjustable speed control.

YS Instruction Register Mode:

InstructionOP-0OP-1Description
YS 03E8 000003E8(immediate)0000(ms)Standard mode: delay 1000ms
YS 0020 FF000020(R20)FF+unitRegister mode: FF means read duration from R20, low byte 00 means unit ms

Register Plan:

RegisterValuePurpose
R200080Delay duration = 128ms (modifiable at runtime, adjusts waterfall speed)
R013300Color R value (high byte = 33)
R023300Color G value (high byte = 33)
R033300Color B value (high byte = 33)
R04-R060000All-zero colors for clearing LEDs

E5 Instruction Parameter Changes (Waterfall Version):

PhaseOP00OP01OP10OP11Effect
Sequential on01010001โ†’0CLight 1โ†’12 LEDs
Sequential off0101000Bโ†’01Light 11โ†’1 LEDs (right side turns off sequentially)
Final clear0401000CAll off

Click to expand/collapse Register-based Delay Waterfall Full Code
000 10 0020 0080
001 10 0001 3300
002 10 0002 3300
003 10 0003 3300
004 10 0004 0000
005 10 0005 0000
006 10 0006 0000
010 E5 0101 0001
011 02 0020 FF00
012 E5 0101 0002
013 02 0020 FF00
014 E5 0101 0003
015 02 0020 FF00
016 E5 0101 0004
017 02 0020 FF00
018 E5 0101 0005
019 02 0020 FF00
01A E5 0101 0006
01B 02 0020 FF00
01C E5 0101 0007
01D 02 0020 FF00
01E E5 0101 0008
01F 02 0020 FF00
020 E5 0101 0009
021 02 0020 FF00
022 E5 0101 000A
023 02 0020 FF00
024 E5 0101 000B
025 02 0020 FF00
026 E5 0101 000C
027 02 0020 FF00
028 02 0200 0000
029 E5 0101 000B
02A 02 0020 FF00
02B E5 0101 000A
02C 02 0020 FF00
02D E5 0101 0009
02E 02 0020 FF00
02F E5 0101 0008
030 02 0020 FF00
031 E5 0101 0007
032 02 0020 FF00
033 E5 0101 0006
034 02 0020 FF00
035 E5 0101 0005
036 02 0020 FF00
037 E5 0101 0004
038 02 0020 FF00
039 E5 0101 0003
03A 02 0020 FF00
03B E5 0101 0002
03C 02 0020 FF00
03D E5 0101 0001
03E 02 0020 FF00
03F E5 0401 000C
040 02 0020 FF00
041 0E 0000 0010

Key Optimization Notesโ€‹

ImprovementPrevious MethodNew MethodComparison
Delay methodYS 0080 0000 (hardcoded 128ms)YS 0020 FF00 (read from R20)Modify R20 to adjust global speed, no need to modify each delay instruction line
Lighting methodE4 sets individual LED one by oneE5 0101 00NN batch settingReduced from 12 instructions to 1 instruction
Clear methodE4 clears one by one or E5 clears all at onceE5 achieves sequential clear by reducing countDemonstrates flexibility of E5 OP11 parameter

YS Register Mode Analysisโ€‹

Using YS 0020 FF00 as example:

PartValueMeaning
OP-00020Register number 20 (i.e. R20), reads duration value from it
OP-1 (high byte)FFSpecial marker: indicates register mode, not standard delay
OP-1 (low byte)00Unit: 00 = milliseconds

Current R20 = 0080 = 128 (decimal), so each delay is 128ms. To speed up the waterfall, change FZ 0020 0080 on line 000 to FZ 0020 0040 (64ms) to make all delays uniformly faster.


Moon Phase Simulation (E5 Optimized Version: Brightness Fade + Batch Operation)โ€‹

Key Improvements: Compared to the original moon phase simulation (DZ jump chain + E4 individual LED control with hardcoded colors), this optimized version features:

  1. E5 Batch Operation: One E5 instruction lights/extinguishes multiple LEDs at once, replacing the original 12 DZ jumps + 12 E4 instructions
  2. Register-stored Brightness: R01-R03 store current moonlight RGB values, dynamically updated through moon phases, enabling brightness gradient from new moon to full moon
  3. R20 Register Delay: Delay duration stored in R20, referenced via YS 0020 FF00, allowing runtime adjustment of overall speed
  4. Changing OP11 LED Count: Similar to the waterfall light idea, LED count changes via E5's OP11 parameter, replacing jump chains

Moonlight Colors (Cool White, Changes with Brightness):

PhaseRGBRegister Value (High Byte)Description
New Moon202040R01=2000, R02=2000, R03=4000Faint moonlight
Waxing Crescent404080R01=4000, R02=4000, R03=8000Brightening
First Quarter6060C0R01=6000, R02=6000, R03=C000Medium brightness
Waxing GibbousA0A0E0R01=A000, R02=A000, R03=E000Brighter
Full MoonE0E0FFR01=E000, R02=E000, R03=FF00Brightest moonlight

Register Planning:

RegisterInitial ValuePurpose
R200080Delay duration = 128ms (modifiable to adjust moon phase speed)
R012000Moonlight R value (updated through phases, uses high byte)
R022000Moonlight G value (updated through phases, uses high byte)
R034000Moonlight B value (updated through phases, uses high byte)
R040000Extinguish R = 00
R050000Extinguish G = 00
R060000Extinguish B = 00

E5 Instruction Parameter Changes (Moon Phase Version):

PhaseOP00OP01OP10OP11 ChangeBrightness ChangeEffect
Waxing (Brightening)01010001โ†’0CR/G/B values increase1 to 12 LEDs, brightness level increases every 2 steps
Waning (Dimming)0101000Bโ†’01R/G/B values decrease11 to 1 LEDs, brightness level decreases every 2 steps
Final Extinguish0401000CAll zeroAll extinguished, returns to new moon state

Click to expand/collapse E5 Optimized Moon Phase Simulation Full Code
000 10 0020 0080
001 10 0001 2000
002 10 0002 2000
003 10 0003 4000
004 10 0004 0000
005 10 0005 0000
006 10 0006 0000
010 E5 0101 0001
011 02 0020 FF00
012 E5 0101 0002
013 02 0020 FF00
014 10 0001 4000
015 10 0002 4000
016 10 0003 8000
017 E5 0101 0003
018 02 0020 FF00
019 E5 0101 0004
01A 02 0020 FF00
01B 10 0001 6000
01C 10 0002 6000
01D 10 0003 C000
01E E5 0101 0005
01F 02 0020 FF00
020 E5 0101 0006
021 02 0020 FF00
022 10 0001 A000
023 10 0002 A000
024 10 0003 E000
025 E5 0101 0007
026 02 0020 FF00
027 E5 0101 0008
028 02 0020 FF00
029 E5 0101 0009
02A 02 0020 FF00
02B E5 0101 000A
02C 02 0020 FF00
02D 10 0001 E000
02E 10 0002 E000
02F 10 0003 FF00
030 E5 0101 000B
031 02 0200 FF00
032 E5 0101 000C
033 02 0200 FF00
034 02 0200 FF00
035 10 0001 A000
036 10 0002 A000
037 10 0003 E000
038 E5 0101 000B
039 02 0020 FF00
03A E5 0101 000A
03B 02 0020 FF00
03C E5 0101 0009
03D 02 0020 FF00
03E E5 0101 0008
03F 02 0020 FF00
040 10 0001 6000
041 10 0002 6000
042 10 0003 C000
043 E5 0101 0007
044 02 0020 FF00
045 E5 0101 0006
046 02 0020 FF00
047 E5 0101 0005
048 02 0020 FF00
049 10 0001 4000
04A 10 0002 4000
04B 10 0003 8000
04C E5 0101 0004
04D 02 0020 FF00
04E E5 0101 0003
04F 02 0020 FF00
050 10 0001 2000
051 10 0002 2000
052 10 0003 4000
053 E5 0101 0002
054 02 0020 FF00
055 E5 0101 0001
056 02 0020 FF00
057 E5 0401 000C
058 02 0200 FF00
059 0E 0000 0010

Key Optimization Comparison: Original vs E5 Optimizedโ€‹

DimensionOriginal Moon Phase SimulationE5 Optimized Moon Phase Simulation
Lighting MethodDZ jump chain + individual E4 per LEDE5 0101 00NN batch lighting (change OP11)
Lighting Instructions~12 DZ + 12 E4 = 24 instructions~24 E5 (but each controls N LEDs, cleaner)
Brightness ControlHardcoded cool white (E0,E0,FF), no variationDynamic R01-R03 updates, 5-level brightness gradient โœจ
Delay DurationHardcoded YS 0100 0000YS 0020 FF00 reads from R20, runtime adjustable
Direction SwitchingDZ comparison + subroutine callsSequential execution (waxโ†’waneโ†’cycle), no complex jumps

Brightness Change Timelineโ€‹

PhaseLine RangeLED Count ChangeRGB Brightness Change
Early Waxing010-0131โ†’2(20,20,40) Faint
Mid Waxing014-0213โ†’6(40,40,80) โ†’ (60,60,C0) Brightening
Late Waxing022-02C7โ†’10(A0,A0,E0) Bright
Full Moon02D-03411โ†’12(E0,E0,FF) Brightest โœจ
Early Waning035-03F11โ†’8(A0,A0,E0) Dimming
Mid Waning040-0487โ†’5(60,60,C0) Dimmer
Late Waning049-0564โ†’1(40,40,80) โ†’ (20,20,40) Dim
New Moon057-059All off(00,00,00) ๐ŸŒ‘

Adjustable Brightness: How to Customize Moonlight Colorโ€‹

To change moonlight color or brightness, simply modify the register initialization values:

Desired EffectWhich Lines to ModifyExample Values
Cooler blue lightLine 003 R03FZ 0003 FF00 (B = FF)
Warmer yellow lightLines 001-002 R01-R02FZ 0001 F000, FZ 0002 F000
Overall dimmerLines 001-003 halve alle.g., FZ 0001 1000, FZ 0002 1000, FZ 0003 2000
Faster moon phaseLine 000 R20FZ 0020 0040 (Delay = 64ms)

Community Library Smart Access Control System (100-Point Demo)โ€‹

Hardware Requirementsโ€‹

  • 1 servo motor with pointer (WPWM instruction, channel 0)
  • 1 full-color LED (CD / E4 instruction)
  • Display device (digital output / serial โ€” shows current person count)
  • Two infrared sensors (outside: Sensor A, inside: Sensor B)
  • 1 staff emergency button

Core Opcodes: 10 (FZ) init ยท 11 register copy ยท 12 inc/dec ยท 13 register โ†’ digital output (display) ยท WPWM (C8) servo control ยท CD (E4) LED color ยท 02 (YS) delay ยท 0E (ZY) jump ยท 09 conditional jump (equal) ยท 04 conditional jump (greater than) ยท 06 conditional jump (equal literal)

Scenario: Bidirectional Entry/Exit Detectionโ€‹

Inside the library: max 10 people.

  • Green LED when count < 10 โ†’ space available โœ…
  • Red LED when count == 10 โ†’ no space ๐Ÿšซ
  • Servo horizontal pointer โ†’ door closed
  • Servo vertical-down pointer โ†’ door open
  • Sensor A (outside) โ†’ Sensor B (inside) โ†’ person entering โ†’ count++
  • Sensor B (inside) โ†’ Sensor A (outside) โ†’ person exiting โ†’ count--
  • Staff button โ†’ always opens door, does NOT change count (extended feature)

Sensor Input Values (R3F)โ€‹

R3F ValueMeaning
0000No button / sensor pressed
0001Sensor A (outside) triggered
0002Sensor B (inside) triggered
0004Staff emergency button

Register Mapโ€‹

RegisterPurposeInitial Value
R09Current person count (0-10)0000
R0ADoor state (0=closed, 1=open)0000
R0BMax capacity constant (10)000A
R0CTemporary / comparison0000
R0DPrevious R3F value (edge detection)0000
R0ESequence memory (0=none, 1=A seen, 2=B seen)0000
R0FSequence timeout counter0000
R10Direction detected (0=none, 1=enter, 2=exit, 3=staff)0000
R20Door-open delay counter00A0
R21Sequence timeout threshold (8 loops)0008
R22Constant 1 (for decrement compare)0001

Servo Positions (WPWM โ€” Channel 0)โ€‹

PositionWPWM InstructionMeaning
HorizontalWPWM 0000 0300Door closed
Vertical downWPWM 0000 0C00Door open

LED Color Referenceโ€‹

ColorCD Instruction (LED00)
Green (has space)CD 0000 9900
Red (full โ€” no space)CD 0099 0000
OffCD 0000 0000

Complete Instruction Code (โ‰ˆ90 lines total)โ€‹

================== Initialization (000-00E) ==================
000 10 0009 0000 R09 = 0 (count = 0, library is empty)
001 10 000A 0000 R0A = 0 (door = closed)
002 10 000B 000A R0B = 10 (max capacity, constant)
003 10 000D 0000 R0D = 0 (previous R3F = nothing)
004 10 000E 0000 R0E = 0 (no sequence detected yet)
005 10 000F 0000 R0F = 0 (sequence timeout counter)
006 10 0010 0000 R10 = 0 (no direction detected)
007 10 0020 00A0 R20 = A0 (door open duration)
008 10 0021 0008 R21 = 8 (reset sequence after 8 empty loops)
009 10 0022 0001 R22 = 1 (constant for comparisons)
00A C5 0001 0000 Enable PWM generator (required for servo)
00B WPWM 0000 0300 Servo channel 0 โ†’ horizontal (door closed)
00C CD 0000 9900 LED00 = green (space available!)
00D 13 0009 0000 Digital output = R09 (display count "0")

================== Main Loop: Read Sensors (010-01F) ==================
010 11 0000 003F R00 = R3F (read current button/sensor state)
011 09 0000 0030 If R00==0: jump to 030 (no input, check timeout)

--- Edge detection: new press = R00!=0 AND R0D==0 ---
012 11 0001 000D R01 = R0D (previous state)
013 09 0000 0017 If R01==0: jump to 017 (new press detected)
014 ZY 0000 0020 Else: jump to count check (sensor still held โ€” skip)

--- New press detected โ€” route by sensor value ---
017 11 000D 0000 R0D = R00 (save current state for edge detection next loop)
018 09 0001 0040 If R00==1: jump to 040 (Sensor A โ€” outside)
019 09 0002 0050 If R00==2: jump to 050 (Sensor B โ€” inside)
01A 09 0004 0060 If R00==4: jump to 060 (Staff button โ€” emergency open)
01B ZY 0000 0020 Unknown input: jump to count check

================== Count Check & LED Update (020-02F) ==================
020 11 0000 0009 R00 = R09 (current count)
021 11 0001 000B R01 = R0B (max capacity = 10)

--- If count >= 10 โ†’ RED LED (full) ---
022 04 0009 0028 If R00 > 9: jump to 028 (>=10 means full)
023 09 000A 0028 If R00==10: jump to 028 (exactly full)

--- Else โ†’ GREEN LED (space available) ---
024 CD 0000 9900 LED00 = green โœ…
025 ZY 0000 002A Jump to display

--- Full capacity: turn LED RED ---
028 CD 0099 0000 LED00 = red ๐Ÿšซ
029 ZY 0000 002A Jump to display

--- Display current count on digital output pins ---
02A 13 0009 0000 Output = R09 (display current count)
02B ZY 0000 0070 Jump to delay/return

================== No-Input Timeout Handling (030-03F) ==================
030 10 000D 0000 R0D = 0 (no input โ†’ reset edge detection)
031 09 0000 0020 If R0E==0: jump to count check (no sequence to timeout)
032 12 000F 0001 R0F += 1 (increment timeout counter)
033 11 0000 000F R00 = R0F
034 04 0007 0020 If R0F > 7: jump to count check (within threshold)
035 10 000E 0000 R0E = 0 (timeout: reset sequence memory)
036 10 000F 0000 R0F = 0 (reset timeout counter)
037 ZY 0000 0020 Jump to count check

================== Sensor A (Outside) Processing (040-04F) ==================
040 11 0000 000E R00 = R0E (what was seen before?)
041 09 0002 0048 If R0E==2: jump to 048 (B then A = person EXITING!)
042 09 0001 0045 If R0E==1: jump to 045 (A already seen โ€” ignore)
043 10 000E 0001 R0E = 1 (first sensor: A was seen โ†’ remember)
044 ZY 0000 0020 Jump to count check (wait for second sensor)

045 10 000F 0000 R0F = 0 (reset timeout: sensor still active)
046 ZY 0000 0020 Jump to count check

--- B then A sequence confirmed โ†’ person EXITING through door ---
048 11 0000 0009 R00 = R09 (check current count)
049 09 0000 0020 If count==0: jump to count check (can't go below 0!)
04A 2B 0009 0001 R09 -= 1 (count = count - 1)
04B 10 0010 0002 R10 = 2 (direction = EXIT)
04C 10 000E 0000 R0E = 0 (reset sequence memory)
04D ZY 0000 0080 Jump to door action (open door)

================== Sensor B (Inside) Processing (050-05F) ==================
050 11 0000 000E R00 = R0E (what was seen before?)
051 09 0001 0058 If R0E==1: jump to 058 (A then B = person ENTERING!)
052 09 0002 0055 If R0E==2: jump to 055 (B already seen โ€” ignore)
053 10 000E 0002 R0E = 2 (first sensor: B was seen โ†’ remember)
054 ZY 0000 0020 Jump to count check (wait for second sensor)

055 10 000F 0000 R0F = 0 (reset timeout: sensor still active)
056 ZY 0000 0020 Jump to count check

--- A then B sequence confirmed โ†’ person ENTERING through door ---
058 11 0000 0009 R00 = R09 (check current count)
059 04 0009 0020 If count > 9: jump to count check (full! can't enter)
05A 12 0009 0001 R09 += 1 (count = count + 1)
05B 10 0010 0001 R10 = 1 (direction = ENTER)
05C 10 000E 0000 R0E = 0 (reset sequence memory)
05D ZY 0000 0080 Jump to door action (open door)

================== Staff Emergency Button (060-07F) ==================
060 10 0010 0003 R10 = 3 (staff action โ€” don't change count!)
061 ZY 0000 0080 Jump to door action (open door regardless)

================== Door Action: Open โ†’ Delay โ†’ Close (080-08F) ==================
080 WPWM 0000 0C00 Servo โ†’ vertical down (DOOR OPEN โ†“)
081 10 000A 0001 R0A = 1 (door state = open)
082 02 0020 FF00 Delay (hold door open for entry/exit)
083 WPWM 0000 0300 Servo โ†’ horizontal (DOOR CLOSED โ€”)
084 10 000A 0000 R0A = 0 (door state = closed)
085 10 0010 0000 R10 = 0 (clear direction)
086 ZY 0000 0020 Jump to count check & LED update

================== Small Delay & Loop Back (070) ==================
070 02 0001 0000 Short delay (debounce)
071 ZY 0000 0010 Loop back to main loop

How It Works: Step-by-Step Flowโ€‹

START
โ”‚
โ–ผ
Initialize registers, servo closed (horizontal), LED green
โ”‚
โ–ผ
Main Loop โ”€โ”€โ–บ Read R3F (sensors/buttons)
โ”‚ โ”‚
โ”‚ โ”œโ”€โ–บ R3F==0 โ†’ no input โ†’ check sequence timeout โ†’ LED update
โ”‚ โ”‚
โ”‚ โ”œโ”€โ–บ R3F==1 โ†’ Sensor A (outside)
โ”‚ โ”‚ โ”œโ”€โ–บ R0E==2 โ†’ B then A โ†’ count-- โ†’ OPEN DOOR
โ”‚ โ”‚ โ””โ”€โ–บ else โ†’ R0E=1 (remember A), continue
โ”‚ โ”‚
โ”‚ โ”œโ”€โ–บ R3F==2 โ†’ Sensor B (inside)
โ”‚ โ”‚ โ”œโ”€โ–บ R0E==1 โ†’ A then B โ†’ count++ (if <10) โ†’ OPEN DOOR
โ”‚ โ”‚ โ””โ”€โ–บ else โ†’ R0E=2 (remember B), continue
โ”‚ โ”‚
โ”‚ โ””โ”€โ–บ R3F==4 โ†’ Staff button โ†’ OPEN DOOR (no count change)
โ”‚
โ–ผ
Update LED: green if count<10, red if count==10
โ”‚
โ–ผ
Display count on digital output pins
โ”‚
โ–ผ
Loop back โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Test Scenarios (Expected Results)โ€‹

Initial CountActionExpected New CountLEDServo
0Sensor A then B (enter)1GreenOpen โ†’ Close
1Sensor A then B (enter)2GreenOpen โ†’ Close
9Sensor A then B (enter)10RedOpen โ†’ Close
10Sensor A then B (enter)10 (unchanged โ€” full!)RedN/A (won't open)
1Sensor B then A (exit)0GreenOpen โ†’ Close
0Sensor B then A (exit)0 (unchanged โ€” can't go below 0)GreenN/A
AnyStaff button (0x04)UnchangedSameOpen โ†’ Close

Key Algorithm Conceptsโ€‹

1. Bidirectional Detection (The Core Innovation) Two sensors positioned on opposite sides of the door detect direction:

  • Sensor A is mounted on the outside of the library
  • Sensor B is mounted on the inside of the library
  • The sequence in which sensors are triggered determines direction:
    • A โ†’ B = walking in (entering library)
    • B โ†’ A = walking out (leaving library)
  • A sequence timeout (R0F counter) resets memory if a person doesn't complete the crossing

2. Edge Detection (Prevent Double-Counting) R0D stores the "previous R3F value." A sensor is only processed when:

  • Current R3F != 0 AND previous R3F == 0
  • This means we only react to the press edge, not the continuous hold
  • Essential for preventing the same person from being counted multiple times

3. Boundary Enforcement

  • Cannot enter when count == 10 (library is full)
  • Cannot exit when count == 0 (library is empty โ€” safety check)
  • Count register (R09) is protected by bounds check before increment/decrement

4. Staff Override (Extended Feature) The staff button at R3F==4 always opens the door without changing the count. This is essential for:

  • Library staff entering/exiting without being counted as visitors
  • Emergency situations where someone is stuck
  • Maintenance access

Customization Tipsโ€‹

What to ChangeWhich Register/LineExample
Library capacityLine 002 (R0B)10 000B 0014 โ†’ capacity = 20
Door open durationLine 007 (R20)10 0020 00FF โ†’ longer open time
Sequence timeoutLine 008 (R21)10 0021 0004 โ†’ faster reset (shorter person)
Servo positionsLines 00B and 080/083WPWM 0000 0500 โ†’ different angle
LED colorLines 00C, 024, 028CD 0000 00FF โ†’ blue LED