Sie sind auf Seite 1von 9

Main Cube Project Page

53 LED CUBE Controller


for PIC16F688
Drawing processor commands

Overview

Instruction set

Instruction details

Controlling the LED Cube Display


The problem with using a data lookup table to drive the LED cube is the amount of data needed. If the data is packed it
requires 16 bytes to hold the state of the cube (125 / 8 = 15.625). Since the 16F688 PIC only has 4K words of program
memory and the main code uses ~1455 words that only leaves about 2600 words for table data. This in turn is room for
only 168 complete cube states to be held in memory so if you wanted the text 'PICPROJECTS' to be displayed, shifting from
the back to the front of the cube it would require 16 bytes x 5 frames per letter x 11 letters = 880 bytes.
Clearly the table lookup method isn't going to allow you to do very much before program memory runs out. To get round this,
the cube is controlled using a macro command language that controls a virtual drawing processor. Using code written with
the macro commands defined for the cube drawing processor the same animation can be done in 60 bytes. (See example
code dpcode.txt)
The instructions are implemented using assembler Macros, for this reason the instruction mnemonics have to be different to
the PIC instruction set and MPASM assembler reserved words. The instruction Macro names and register names are
uppercase and case sensitive. The Macro instructions are converted into either one or two PIC assembler retlw instructions
at assembly time. When the PIC ledcube firmware runs it reads these back as table data, decodes the instruction based on
bit-fields and then calls assembler functions to perform the required drawing processor operation.
The Drawing Processor has 72 instruction, 8 registers, and a 33 level user stack. The instruction set is similar to PIC
assembler and you will need to have knowledge of PIC assembly language programming and the Microchip MPASM / MPLAB IDE
if you intend to write your own routines using it. Also an understanding of postfix stack operation wouldn't hurt.
Since the DP code is generated from MPASM macros and just ends up being assembled with the rest of the PIC program
code, all the usual MPASM operators and number formats are available to use when writing code for the DP.
Demo Code
The pre-assembled HEX file for the LED cube projects contains some demo animation sequences. The Drawing Processor
code for this is contained in the file CubeProgram.inc
Overview
In the context of this project, a Voxel is a single LED within the cube whose position is defined by its X,Y & Z coordinates.
Registers
The DP has 8 registers; 4 general purpose and 4 special purpose. All registers are 8 bits wide and can hold a value in the
range 0-255. However, instructions that use values in the special function registers expect the value to be within the range
shown in the table below. Values outside this range may result in unpredictable code execution.
Register name

Function

Range

R0

General purpose register

0-255

R1

General purpose register

0-255

R2

General purpose register

0-255

R3

General purpose register

0-255

RHOLD

Hold time value for SHOW command ( x 10mS)

0-255

RX

X co-ordinate for voxel and drawing functions

0-4

RX

X co-ordinate for voxel and drawing functions

0-4

RY

Y co-ordinate for voxel and drawing functions

0-4

RZ

Z co-ordinate for voxel and drawing functions

0-4

Timer
There is a single user timer that counts from a preloaded value down to zero in 1 second intervals.
Stacks
The DP has two stacks, a user stack and a return address stack. The return address stack holds the return address for Jump
to Subroutine (JSR) instructions and is not directly accessible. The user stack is 33 levels deep and can be used to push/pull
any user register. It is also used to perform math and logical operations by pushing the values on to the stack, then
executing the operation, the result being pushed back onto the stack. To that end DUP, DROP, SWAP, OVER and ROT stack
operators are also implemented. This is a similar to the FORTH programming language and not by coincidence:-).
The user stack pointer has wrap around capability so unmatched push/pull operations won't overwrite memory outside
the stack
This is important as the ADD/SUB/OR/AND/XOR operators always push the result of the operation onto the stack. This
means you don't have to pull the result unless you need it, but you should remember it is on the stack if you have
something else pushed on the stack previously. See also DROP instruction which discards the entry on the top-ofstack.
The user stack can hold a maximum of 33 entries.
Be aware that the PUSHXYZ and PULLXYZ instructions use 3 stack entries.
The return address stack does not wrap and has no over/under flow checking.
The return address stack can hold up to 8 return addresses.
Flags
Fcarry - Set if carry occurred during add instruction, cleared if no borrow occurred during subtract (same as underlying
PIC operations)
Fzero - Set if result was zero, cleared if result was non-zero. Fzero flag is also modified by TSTVOX, CMP, Timer and
external switch instructions.
Instruction Set
r - register name
k - literal, constant data or label
Mnemonic

Description

NOOP

No operation

MSET

Modify operations will set voxel to on

MCLR

Modify operations will set voxel to off

MINV

Modify operations will invert current voxel value

SETALL

Turn on all voxels in cube (independant of MSET, MCLR and MINV instructions)

CLRALL

Turn off all voxels in cube (independant of MSET, MCLR and MINV instructions)

INVALL

Invert all voxels in cube (independant of MSET, MCLR and MINV instructions)

SHOW

Transfer drawing buffer to display and load value in RHOLD register into hold
timer

Flags Register

VOX k,k,k

Load RX, RY, RZ and modify voxel

[ 0 <= k <= 4 ]

RX,RY,RZ

VOXM

Modify voxel at current RX, RY, RZ co-ordinates

TSTVOX

Test voxel at current RX, RY, RZ co-ordinates.


Fzero clear if voxel on : Fzero set if voxel off

CHYR r

Draw ASCII character specified in register r in the Y (vertical) plane

CHZR r

Draw ASCII character specified in register r in the Z (horizontal) plane

CHY k

Draw ASCII character value k in the Y (vertical) plane [32 <= k <= 95]

CHZ k

Draw ASCII character value k in the Z (horizontal) plane [32 <= k <= 95]

LINE k,k,k,k

Modify a line of voxels, specify x inc, y inc, z inc, length

LINEX

Modify line of voxels across the whole X axis, located at RY,RZ

LINEY

Modify line of voxels across the whole Y axis, located at RX,RZ

LINEZ

Modify line of voxels across the whole Z axis, located at RX,RY

PLANEX

Modify all voxels in the YZ plane, located in the X-axis at RX

PLANEY

Modify all voxels in the XZ plane, located in the Y-axis at RY

PLANEZ

Modify all voxels in the XY plane, located in the Z-axis at RZ

ROTATEX

Rotate entire cube along a line at y=2, z=2 in the x-axis

SHXL

Shift entire drawing buffer left one voxel.

SHXR

Shift entire drawing buffer right one voxel.

SHYU

Shift entire drawing buffer up one voxel

SHYD

Shift entire drawing buffer down one voxel

SHZF

Shift entire drawing buffer forward one voxel

SHZB

Shift entire drawing buffer back one voxel

DECX

Decrement RX register, modulo 5

Fzero RX

DECY

Decrement RY register, modulo 5

Fzero RY

DECZ

Decrement RZ register, modulo 5

Fzero RZ

INCX

Increment RX register, modulo 5

Fzero RX

INCY

Increment RY register, modulo 5

Fzero RY

INCZ

Increment RZ register, modulo 5

Fzero RZ

DECR r

Decrement register, modulo 256

Fzero r

DECRSZ r

Decrement register, modulo 256, Skip next instruction if result is zero

INCR r

Increment register, modulo 256

INCRSZ r

Increment register, modulo 256, Skip next instruction if result is zero

PUSHR r

Push register contents onto top of stack

PULLR r

Pull top of stack and place contents into register

PUSHXYZ

Push registers RX, RY, RZ on to stack

PULLXYZ

Pull registers RX, RY, RZ from stack

Fzero

RX,RY,RZ

r
Fzero r
r

RX,RY,RZ

PULLXYZ

Pull registers RX, RY, RZ from stack

DROP

Pull entry from top of stack and discard it ( a -- )

SWAP

Swap top two entries on stack. ( a b -- b a )

DUP

Duplicate entry on top of stack.

OVER

Operates on the stack : (a b -- a b a )

ROT

Operates on the stack : ( a b c -- b c a)

TSTZ

Test value on top of stack and condition Fzero flag (a -- a ) : a==0 Fzero set,
a != 0 Fzero clear

Fzero

ADD

pulls two values from the stack, adds them together and pushes result back
onto stack

Fzero
Fcarry

SUB

pulls two values from the stack, subtracts them and pushes result back onto
stack
order is (TopOfStack-1) - (TopOfStack) -> TopOfStack

Fzero
Fcarry

AND
OR

pulls
onto
pulls
onto

RX,RY,RZ

(a b -- a a b )

two values from the stack, performs a bitwise 'AND' result is pushed back
stack
two values from the stack, performs a bitwise 'OR' result is pushed back
stack

Fzero
Fzero

XOR

pulls two values from the stack, performs a bitwise 'XOR' result is pushed back
onto stack

Fzero

NOT

pull value from top of stack, perform bitwise 'NOT' operation on byte and push
result back on to stack

Fzero

CMP r, k

Compare register contents with k. If contents of r == k then Fzero Set, else


Fzero Cleared.

Fzero

LDXYZ k,k,k

Load RX, RY, RZ

LDR r,k

Load register with value k

LDRAND r,k

Load register with random number in the range [ 0 <= Random Number < k ]

LDTMR k

Load timer with period in seconds [1 <= k <= 255 ]

ADDTRND k

Add random number in the range [ 0 <= Random Number < k ] to contents of
Timer

SKIPZ

Skip next instruction if Fzero flag is set

SKIPNZ

Skip next instruction if Fzero flag is clear

SKIPC

Skip next instruction if Fcarry flag is set

SKIPNC

Skip next instruction if Fcarry flag is clear

SKIPTOUT

Skip next instruction if Timer == 0

JUMP k

Jump to program address k

JSR k

Jump to subroutine at address k

RET

Return from subroutine

RANDSEED

Seed random number generator with non-zero value from TMR0

SYNCEXT k

Wait for a falling edge on SW1 input before continuing program execution or
timer out

Fzero

TSTSW

Test SW1 input. Set Fzero flag if switch active (pressed), Clear Fzero flag if
switch not active

Fzero

Instruction details

SHOW

[ 0 <= k <= 4 ]

(see also VOX k,k,k)

RX,RY,RZ

[0 <= k <= 255 ]

r
r

SHOW
All drawing instructions operate on the drawing buffer. This allows a new image to be built up in the drawing buffer while the
LED cube displays the contents of the display buffer. To transfer the drawing buffer into the display buffer you must use the
SHOW instruction. When the show instruction is executed it will wait for the previous hold delay to complete if it is still
active. It then sets the buffer transfer flag and waits for the display driver to copy the drawing buffer into the display buffer
and clear the transfer flag. At this time the value in RHOLD is transferred into the hold timer and the instruction exits.
RHOLD timer is period to wait x 10mS.

If RHOLD is 0, the buffer is transferred at the next cube display refresh.

This command is blocking, program execution will not continue until the current hold timer has timed out and the interrupt
display driver has transferred the buffer.

MSET, MCLR, MINV instructions control the operation of VOX, PUT, LINE and PLANE instructions.
MSET turns on voxels
MCLR turns off voxels
MINV inverts the current voxel state
The operating mode remains in effect until changed by another instruction.

VOX RX, RY, RZ / VOXM / TSTVOX instructions operate on a single Voxel


The voxel is modified according to current mode set by MSET / MCLR / MINV instruction.
VOX RX, RY, RZ loads co-ordinates into RX, RY, RZ and modifies the voxel
VOXM modifies the voxels using current RX, RY and RZ co-ordinates
TSTVOX test the voxel at the current RX,RY,RZ co-ordinates and then sets the Fzero flag.
Fzero flag is cleared if the voxel is on, Fzero is set if the voxel is off

SETALL, CLRALL and INVALL instructions operate on the entire cube


These instructions operate independently of the current Voxel mode set by the MSET, MCLR, MINV instructions.

Stack operations
Stack Notation:
( stack before -- stack after ) e.g. SWAP
PUSHXYZ
PULLXYZ

( a b -- b a )

( -- Z Y X)
( Z Y X -- )

These two instructions push and pull the X,Y and Z registers to/from the user stack in a single command. The order the
registers are pushed onto the stack is X-Y-Z, so the Z register is at the top-of-stack after a PUSHXYZ instruction.
PUSHR Rn
PULLR Rn

( -- Rn)
( Rn -- )

Push or pull the single register to/from the top of the user stack
DROP ( a -- )
discards the top entry from the stack
SWAP ( a b -- b a )
swaps the top two values on the stack
DUP ( a -- a a )
duplicates the top entry onto the top of the stack
OVER (a b -- a b a )
inserts copy of the top stack entry behind the second entry
ROT ( a b c -- b c a)
rotates the top three entries on the stack.

LDTMR, ADDTRND and SKIPTOUT instructions control the operation of a user timer.
The timer is loaded with the number of seconds required for the timer period. It then counts down until it reaches zero and
stops. The SKIPTOUT instruction tests the current value in the timer and will skip the next instruction when it reaches zero.
ADDTRND instruction adds a random value between 0 and k-1 to the value already in the timer. This allows the timer to be
loaded with a random value between any two values, by using a LDTMR instruction followed by a ADDTRND instruction.

SYNCEXT
The sync external instruction waits for a falling edge on the S1 input or a timeout before continuing program execution.
If the timeout value is set to 0, the instruction waits indefinitely for a falling edge before continuing. If the timeout value is
set between 1 and 255, the instruction waits until either a falling edge is detected or the timer reaches 0. The timer
decrements at one second intervals and is shared with the other timer instructions. The timer is not cleared if the instruction
exits on a falling edge.
The Fzero flag is set if the instruction exits on a falling edge, and cleared if it exits on a time out.
SYNCEXT 0

; wait indefinitely for falling edge on S1 input before continuing

SYNCEXT 12

; wait for 12 seconds, or failing edge on S1 input before continuing

There is no software debouncing implemented on this control input, it expects a clean logic level signal.
TSTSW
The TSTSW instruction reads the logic level on the switch input. If the logic level is low (switch pressed) the Fzero flag is
set, if the logic level is high (switch not pressed) the Fzero flag is cleared. This instruction is not blocking, the input is
tested, the Fzero flag conditioned and code execution continues.

DECRSZ and INCRSZ instructions do not modify the Fzero flag.


DECR and INCR instructions do modify the Fzero flag.
I appreciate this doesn't seem logical but it reflects the way the underlying PIC instructions work.
INCX, INCY, INCZ and DECX, DECY, DECZ instructions do modify the Fzero flag. These instructions use Modulo 5 for the
increment/decrement so the number increments from 4->0 and decrements from 0->4.
It is important to note that the DECR, INCR, DECRSZ, INCRSZ can be used on all registers including RX, RY, RZ. However,
this can lead to a value in the register that is outside the valid range of 0 =< Rxyz =< 4 since these instructions operate on
the byte modulo 256. Instructions that follow and operate on the values in the RX, RY , RZ registers may cause the
underlying PIC firmware to crash if the value is outside of the expected range.

SHXL, SHXR, SHYU, SHYD, SHZF, SHZB instructions shift the entire drawing buffer one voxel in the direction specified.
The voxels at the incoming edge of the shift are cleared (set to off)
Example.
Shift down:
Before

After

LINE x_inc, y_inc, z_inc, length


This instruction modifies a line of voxels.

This instruction modifies a line of voxels.


x_inc, y_inc and z_inc can have a value of -1, 0 or 1
The start point for the line is the current value in RX, RY, RZ
After the voxel at RX,RY,RZ has been modified:
RX = RX + x_inc : RY = RY + y_inc : RZ= RZ + z_inc : Length = Length -1
This repeats until Length == 0
The Line instruction will leave RX, RY and RZ values set to the finish point for the line. This allows
consecutive line instruction to draw a new line starting from the end point of the previous line.
The increment/decrement operation on the registers are modulo 5 so the decrement will roll under from 0
back to 4 and the increment rolls over from 4 to 0
examples
MSET
LDXYZ 0,0,0
LINE 1, 1, 1, 5

MSET
LDXYZ 0,4,2
LINE 0, -1, 1, 2

plots a line thro ugh the following vox e ls

plots a line through the following vo x e ls

RX

RY

RZ

RX

RY

RZ

MSET
LDXYZ 2,2,2
LINE -1, 0, 1, 4

MSET
LDXYZ 0,0,0
LINE 0, 0, 1, 5

plots a line thro ugh the following vox e ls

plots a line through the following vo x e ls

RX RY RZ

RX

RY

RZ

0
4

2
2

4
0

<- rollover

LINEX, LINEY, LINEZ


These instructions draw a full length line across one axis in the drawing
buffer.
The voxels in the line will be set, cleared or inverted according to the
current mode set by the most recent MCLR, MSET or MINV instruction.
These three instructions execute faster than using the LINE instruction.

LINEX
located in the Y-Z planes by the current values of RY and RZ
Example of LINEX.

LINEY
located in the X-Z planes by the current values of RX and RZ
LINEZ

Values in RY and RZ registers locate the line in the


YZ axis.
The value of RX register is ignored

located in the X-Y planes by the current values of RX and RY


The RX, RY and RZ register values are unchanged by these
instructions.

PLANEX, PLANEY, PLANEZ


The PLANE instructions fill an entire plane in the drawing buffer.
The voxels in the plane will be set, cleared or inverted according to the current mode set by the most recent MCLR, MSET or
MINV instruction.

Value in RX specifies position along the


X-axis

Value in RY specifies position along the


Y-axis

Value in RZ specifies position along the


Z-axis

CHZ, CHZR, CHY, CHYR


A 5x5 character set has been defined for the ASCII characters in the range 32 to 95. This covers 0-9 and uppercase A-Z
along with most symbols.
The characters can be drawn in the XY plane along the Z-axis or the XZ plane on the Y-axis.
There is no support for drawing characters in the YZ plane.
Character 'A' in the XZ plane
value in RY positions character in the Y plane

Character 'A' in the XY plane


value in RZ positions character in the Z plane

Given the way the PLANEY and PLANEZ commands work you would expect CHY and CHZ commands to work the opposite
way round to the way they do and I wouldn't disagree but if I change it now it breaks any code people may have already
written.

Das könnte Ihnen auch gefallen