Sequencer Mode 1 routine - Set to the Same Color

We'll use the combined file method (i.e., the first method presented) as was used in the prior example. Start by creating Seq_Mode1.Ptr as before, so the Assembler doesn't complain about a missing file. Create a new file named Only_Mode1.Asm and and place this first title and documentation block in it.

/******************************************************************************
*
*                           Routine "SetSameColor"
*
*  Purpose: Output a single color to all pixels specified by LED count.
*
*  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
*
*  Alters:
*
*  Notes:   The WS2812 configuration block (or structure) layout:
*     +---------+-----------+--------+----------+---------+----+----+-/
*     | Display | Bitmapped | Port's | (Inc/Dec | (MaxBrt |   LED   |
*     |   Mode  |GRB| | Port| Pin(s) |  unused) | unused) |  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  |
*             /-+----+----+----+----+-----+------+------+-----+-----+
*               Green  Red Blue  milliSec     Seconds
*
*
*           The GRB (Green-Red-Blue) LED BYTE data image layout:
*      +-----+-----+-------+-------+-------+-------+-------+-------+-/
*      | Byte Count| Green |  Red  | Blue  | Green |  Red  | Blue  |
*      | LSB   MSB | LED#1 | LED#1 | LED#1 | LED#2 | LED#2 | LED#2 |   . . .
*      +-----+-----+-------+-------+-------+-------+-------+-------+-/
*         +0   +1     +2      +3      +4      +5      +6      +7
*
******************************************************************************/

The first two (2) BYTES of code in every Sequencer block are the unique Mode ID then the number of 16-BYTE "sentences" in the module. They're followed by the "LDI R30, I_PushAll" instruction. The code for this Sequencer block is very small, since all it is doing is writing the same 3-BYTE color code to each of the pixels specified.

.IFNDEF ASetSameColor
   .PRINT "Assemble again to initialize label addresses."
   ASetSameColor = 0x102
   AMode1End = 0x144
.ENDIF

Mode1Start:
.BYTE 1                                        ; The MODE byte: Mode 1
.BYTE (AMode1End - ASetSameColor) / 16 + 1     ; Number of 16-byte blocks used

SetSameColor:             ; 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   Use 2-BYTE CALLs/JMP for this example

Mode1_Loop:                  ; Begin the loop; 1 loop for each GRB LED pixel
   ST      Z+, R17           ;  2  2   Write the LED color GREEN component
   ST      Z+, R18           ;  2  2   Write the LED color RED   component
   ST      Z+, R19           ;  2  2   Write the LED color BLUE  component
   SBIW    R26, 1            ;  2  2   Decrement the remaining LED count WORD,
   BRNE    AMode1_Loop       ;  2 1/2   which is maintained in R27:R26

   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

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

Close the Only_Mode1.Asm file then concatenate it to the Seq_Mode0.Asm source from the last example. The copying and assembly results in the output below.

C:\TestDir>Copy /B Seq_Mode0.Asm+Only_Mode1.Asm Seq_Mode1.Asm
Seq_Mode0.Asm
Only_Mode1.Asm
        1 file(s) copied.

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

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

We've encountered this before. Open the Seq_Mode1.Asm source code file and search for the ".INCLUDE Seq_Mode0.Ptr" line. It should still be located at about line 115. Only a single character needs to be changed: the "0" in that line, to a "1". Assemble it again. Since the prior Assembly already created the new line identifier label constants in the .Sym and .Ptr files, simple including the Seq_Mode1.Ptr file resolved all of the missing addresses so the final code contains the missing constants and the warning message is no longer generated.

Examine the Seq_Mode1.Dmp listing to verify that all the new branch instructions near the end of the file actually did resolve as expected. These should be the last few lines of the Seq_Mode1.Hex or Seq_Mode1.Trm iHex image file. The new Mode 1 Sequencer module has 26 BYTEs of code and six (6) BYTEs of 0xFF padding. Just as a reminder, this subroutine's code is NOT relocatable since it uses RCALL and RJMP operations to targets outside of the Sequencer Mode 1 subroutine.

>D+F-H 0x240 32
:100240000102E0E0DDDE64DF119321933193119729
:10025000D9F72C2D211195DFABCFFFFFFFFFFFFF5B
:00000001FF
>                                                                               

This sequence isn't actually called very often since it can be quite jarring to have all of the LEDs quickly change intensity at the same moment. Still, it's here as an example. This is the Seqencer module code which results. It is only 32 BYTEs in length.