Sequencer Mode 2 routine - Lights Up

This time, we'll copy Seq_Mode1.Ptr to Seq_Mode2.Ptr rather than create a blank file. Doint it this way demonstrates that there is more than one way to generate this file. The new Only_Mode2.Asm file is easily started by simply copying the title and documentation block below into it.

/******************************************************************************
*
*                              Routine "LightsUp"
*
*  Purpose: Increase the color components of all GRB pixels in the array to
*           the same value, producing WHITE output.
*
*  Assumes: This routine is a FOREGROUND task (so R15 is valid upon entry.)
*           R29:R28 points to the start of the uVars.B[] array
*               R1  contains the value 0
*
*  Passed:  R24 byte wOffset into the uVars.B[] array for our 16 bytes
*                    if invalid (e.g., 0xFF), 0 will be used instead
*
*  Notes:   The WS2812 configuration block (or structure) layout:
*     +---------+-----------+--------+-----------+--------+----+----+-/
*     | Display | Bitmapped | Port's | Incr/Decr |  Max   |   LED   |
*     |   Mode  |GRB|Z| Port| Pin(s) |  Amount   | Bright |  Count  |   . . .
*     +---------+-3-+1+--4--+--------+-----------+--------+----+----+-/
*         +0         +1         +2        +3         +4     +5   +6
*                 +7   +8   +9   +10, 11      +12, 13     +14   +15
*             /-+----+----+----+----+-----+------+------+-----+-----+
*               | Mode Specific|  Update  | Mode Change | Starting  |
*       . . .   | #1 | #2 | #3 | Interval |  Interval   |  Address  |
*             /-+----+----+----+----+-----+------+------+-----+-----+
*                      unused    milliSec     Seconds
*
******************************************************************************/

The first portion sets the mode ID and calculates the number of 16-BYTE groups that this mode contains. After that is the environment setup and call to the shared initialization routine. The only additional instruction is zeroing R18 to remember after the loop if any changes were made inside the loop.

.IFNDEF ALightsUp
   .PRINT "Assemble again to initialize label addresses."
   ALightsUp = 0x102
   AMode2End = 0x144
.ENDIF

Mode2Start:
.BYTE 2                                        ; The MODE byte: Mode 2
.BYTE (AMode2End - ALightsUp) / 16 + 1         ; Number of 16-byte blocks used

LightsUp:                 ; Bytes Clocks
   LDI     R30, I_PushAll    ;  2  1   Select the routine: PushAll, which MUST
   RCALL   ASoftVector       ;  2  3     use a CALL, not a JUMP!
   RCALL   AShared_Setup     ;  2  3
   LDI     R18, 0            ;  2  1   Initialize to "no pixels have changed"

The next block reads each Green, Red, and Blue component of each pixel's intensity, adds the incremental amount to it, then checks to see if it has exceeded the desired target. If not, it's stored and the change indicator set. If it has, however, it's set to its maximum value. It any pixel has reached its maximum, it is left unchanged.

Mode2_OuterLoop:             ; Begin the loop; 1 loop for each GRB LED pixel
   LDI     R17, 3            ;  2  1   Initialize the Inner Loop for 3 pixels

Mode2_InnerLoop:
   LD      R16, Z            ;  2  2   Read the LED color component; increment
   ADD     R16, R13          ;  2  1    its GREEN / RED / BLUE component value
   CP      R16, R14          ;  2  1
   BREQ    AMode2_Write      ;  2 1/2
   BRCS    AMode2_Write      ;  2 1/2  If it ran past 0, set it to 0 instead
   MOV     R16, R14          ;  2  1    (this also works if it was already 0)

Mode2_Write:
   LDI     R18, 1            ;  2  1   Make note that some pixel changed
   ST      Z+, R16           ;  2  2   Write the new component value and post-
   DEC     R17               ;  2  1    increment the byte position pointer
   BRNE    AMode2_InnerLoop  ;  2 1/2  Loop until all 3 colors are updated

   SBIW    R26, 1            ;  2  2   Decrement the remaining LED count WORD
   BRNE    AMode2_OuterLoop  ;  2 1/2   (kept in R27:R26) until it reaches 0

If the Modal bit ("Z" in the 2nd BYTE as shown in the documentation), it is desired to end the mode upon reaching the desired intensity, rather than wait for the complete duration to expire. The exit and output code follows.

Mode2_Check:
   SBRS    R11, BIT_R11_MODAL;  2 1/2  If the Modal bit in R11 is clear, don't
   RJMP    AMode2_Exit       ;  2  2    check to see if any pixel(s) changed
   CPI     R18, 0            ;  2  1   If any pixels were updated this time,
   BRNE    AMode2_Exit       ;  2 1/2   skip to the exit, otherwise, change
   LDI     R26, 1            ;  2  1    R27:R26 = 0x0001 to cause this mode to
   STD     Y+12, R26         ;  2  2    timeout the next time it is checked,
   STD     Y+13, R27         ;  2  2    thereby advancing to the next mode

Mode2_Exit:
   MOV     R18, R12          ;  2  2   Shared_Output() needs bPortPins in R18
   CPSE    R18, R1           ;  2 1/2  If uVars.B[ n+2 ] is zero, there is no
   RCALL   AShared_Output    ;  2  3    need to call Shared_Output()
   RJMP    AShared_Exit      ;  2  2

Mode2End:
   .BALIGN 16, 0xFF, 15      ; Byte align to 16 boundary; pad with 0xFFs

Close Only_Mode2.Asm append it to Seq_Mode2.Asm, perhaps as shown below then open the new file to edit it.

C:\TestDir>Copy Seq_Mode1.Asm+Only_Mode2.Asm Seq_Mode2.Asm
Seq_Mode1.Asm
Only_Mode2.Asm
        1 file(s) copied.

C:\TestDir>Edit Seq_Mode2.Asm                                            

Find for the line with .INCLUDE "Seq_Mode1.Ptr" change the "1" to a "2", save the file and exit. We're again ready to Assemble the file. The first time we do that, most of the work is done except some addresses are unresolved. The second time, they have been.

C:\TestDir>Assemble Seq_Mode2
Assemble again to initialize label addresses.

C:\TestDir>C:\TestDir>Assemble Seq_Mode2

C:\TestDir>                                                                     

These is the block of code which this Sequencer Mode generates:

:100260000204E0E0CDDE54DF20E013E000810D0D5C
:100270000E1511F008F00E2D21E001931A95B1F73B
:10028000119799F7B4FE05C0203019F4A1E0AC87AE
:10029000BD872C2D211175DF8BCFFFFFFFFFFFFFE7
:00000001FF

This completes the addition of the Mode 2 Sequencer example code to the block containing the shared routines, Modes 0 and Mode 1.