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.