PIC16F84 "retfie" not found in assembly program, yet working

Thread Starter

DonutChan

Joined Mar 3, 2019
33
I tried to understand a program I found for a musical LED cube https://hackaday.io/project/18550-music-ledcube-3x3x3 (the program is there)
but I don't know why there's a lack of a "retfie" command although the existence of an interruption- (also not sure how the randomizing works with the PCL and goto's ,, i only see the PCL register used with retlw commands.)

Mod edit: Thread moved to Embedded Systems - JohnInTX
 
Last edited by a moderator:

MaxHeadRoom

Joined Jul 18, 2013
28,617
Looks very poorly written, no comments.
They use a GIE, interrupt when they want to interrupt and then reset the GIE set in the interrupt vector which is a no-no, it is done automatically After the interrupt is complete when using a retfie!.
Wants rewriting.
Max.
 

AlbertHall

Joined Jun 4, 2014
12,345
retfie enables interrupts and returns so you could enable interrupts and then use a standard return. This program enables interrupts at the start of the interrupt routine so then only a return is needed. I have no idea why it is done that way. I agree with @MaxHeadRoom on the quality of the code.
 

JohnInTX

Joined Jun 26, 2012
4,787
As the others have observed, this code has some ..uh issues. The way it uses the interrupt is unconventional..

The interrupt is used as a beat detector that changes the displayed pattern on each beat. It works like this:

  • The interrupt input is connected to an analog circuit that asserts signals on the interrupt input as the music beats.
  • On a beat, that external interrupt is asserted and a new random pattern is selected by looking at the 3 LSbits of the free running timer and doing a conventional lookup and GOTO(!!) to one of 8 pattern routines.
  • A pattern runs for awhile then jumps back to IdleCube. "Jumps?", you say. Yep. The stack is allowed to just overflow as interrupts occur and wrap around and around.
  • So, the interrupt is used simply as an edge-triggered event that seizes control from the currently running pattern, or IDLE if the pattern completes, and jumps to a new one.
  • Before the jump, the interrupt flag is cleared and interrupt re-enabled so that on the next beat, the process can repeat.
  • The pattern action is performed by brute-force rather than have the patterns stored in tables with a little processing engine to spit out the LED patterns.

As a long time PIC programmer, I am both horrified and twinged with a bit of awe at the implementation. It is breathtakingly bad coding practice but it looks like it works. Amazingly enough, I've actually seen the stack-overflow construct used before in a troubled project I took over some many years ago. Who'd have thunk I'd see another one?

I wouldn't be too optimistic that you could port this to another PIC. As far as I know the stacks quit wrapping around years ago.

Fun stuff!

Code:
;directives
PROCESSOR 16F84A
RADIX HEX
;defs
PCL EQU 0x02
OPTREG EQU 0x01
TMR EQU 0x01
INTCON EQU 0x0B
TMR0 EQU 0x01
TRISB EQU 0x06
TRISA EQU 0x05
PORTA EQU 0x05
PORTB EQU 0x06
STATUS EQU 0x03
FSR EQU 0x04
INDF EQU 0x00
Z EQU 2 ; Z flags
GIE EQU 7 ; GIE bit
INTF EQU 1 ; INTF flag
LOWL EQU 0x20 ; bottom layer (8 bit pattern)
MIDL EQU 0x21 ; middle layer (8 bit pattern)
HIGL EQU 0x22 ; upper layer (8 bit pattern)
EXTL EQU 0x23 ; extra layer (9th led for each layer)
TIME EQU 0x24 ; current frame speed
TCONT EQU 0x25 ; frame speed counter
LSEL EQU 0x26 ; layer selector
BCONT EQU 0x27 ; brightness counter
BRIG EQU 0x28 ; brightness
CURL EQU 0x29 ; current layer
;program start
ORG 0x0000 ; start from address 0x0000
goto Init
ORG 0x0004
Interrupt: ; interrupt service routine
bcf INTCON,INTF
bsf INTCON,GIE ; enabling the interrupt service
movf TMR,0
andlw 0x07
addwf PCL,1
goto Pattern_treble
goto Pattern_updown
goto Pattern_twobars
goto Pattern_buildframe
goto Pattern_rotplane
goto Pattern_rlplane
goto Pattern_snake
goto Pattern_fourface
Init: ; initialization
bsf STATUS,5 ; select RAM bank 1
movlw b'00000001'
movwf TRISB
movlw b'00000000'
movwf TRISA
bcf OPTREG,5 ; start the TMR module in counter mode
bcf STATUS,5 ; select RAM bank 0
movlw 0x00
movwf PORTA
movwf PORTB
clrf LSEL
call IdleCube
;******** ShowLayer **********************************
;
; Shows the layer encoded in W and EXTL for x msec.
; (BRIG/255)% of the time the layer is ON, the
; remaining (255-BRIG)/255)% of the time the layer
; is OFF. (this is a PWM controlled brightness)
;
;*****************************************************
ShowLayer:
; layer on for (255/BRIG)*x msec
; layer off for (255/(255-BRIG))*x msec
; where x depends on the osc used
; set the first seven leds (bit0 of PORTB is used to receive interrupts!)
movwf PORTB ; PORTB <- W
; set/clear the 8th led
btfsc CURL,0
bsf PORTA,2
; test the 9th bit of the current layer and set
; the 9th led accordingly (9th led = bit3 of PORTA)
movf EXTL,0
andwf LSEL,0 ; W <- EXTL & LSEL
btfss STATUS,Z ; is the 9th bit clear (9th led off)?
bsf PORTA,3 ; no, set the 9th bit
; set the 9th bit of the current layer and turn on
; the entire layer
movf LSEL,0
xorwf PORTA,1 ; PORTA <- W ^ LSEL
; wait (BRIG/255)%
movf BRIG,0
movwf BCONT
ShowLayer_loop_layeron:
decfsz BCONT
goto ShowLayer_loop_layeron
; turn off the entire layer
clrf PORTA
; wait ((255-BRIG)/255)%
movf BRIG,0
movwf BCONT
decf BCONT,1
ShowLayer_loop_layeroff:
incfsz BCONT
goto ShowLayer_loop_layeroff
return
;******** ShowCube ***********************************
;
; Shows the cube pattern for 0.01 * TIME sec using
; brightness level BRIG. The refresh rate is 100Hz.
;
;*****************************************************
ShowCube:
; setup counter
movf TIME,0
movwf TCONT ; TCONT <- TIME
ShowCube_loop:
; upper layer
movlw b'00010000'
movwf LSEL ; LSEL = b00010000;
movf HIGL,0
movwf CURL ; loads upper layer
call ShowLayer ; shows upper layer
; mid layer
movlw b'00000010'
movwf LSEL ; LSEL = b00000010;
movf MIDL,0
movwf CURL ; loads mid layer
call ShowLayer ; shows mid layer
; bottom layer
movlw b'00000001'
movwf LSEL ; LSEL = b00000001;
movf LOWL,0
movwf CURL ; loads bottom layer
call ShowLayer ; shows bottom layer
; repeat until TCONT>0
decfsz TCONT,1
goto ShowCube_loop
return
;******** IDLECUBE ***********************************
;
; The cube is glowing and ready to trigger...
;
;*****************************************************
IdleCube:
movlw b'11111111'
movwf LOWL
movlw b'11111111'
movwf MIDL
movlw b'11111111'
movwf HIGL
movlw b'00010011'
movwf EXTL
movlw 0x01
movwf BRIG ; smallest brightness
movlw 0x02
movwf TIME ; smallest pattern duration
bcf INTCON,INTF
bsf INTCON,4 ; enabling the interrupt from the RB0/INT pin
bsf INTCON,GIE ; enabling the interrupt service
IdleCube_fadein: ; fade in loop
call ShowCube
incfsz BRIG
goto IdleCube_fadein
IdleCube_fadeout: ; fade out loop
call ShowCube
decfsz BRIG
goto IdleCube_fadeout
incf BRIG,1
goto IdleCube_fadein
;******** PATTERN BUILDFRAME ************************
;
; Shows a self-building cube frame
;
;*****************************************************
Pattern_buildframe
movlw 0x00
movwf BRIG
movlw 0x40
movwf TIME
Pattern_buildframe_loop:
clrf HIGL
movlw b'10000000'
movwf MIDL
clrf LOWL
clrf EXTL
call ShowCube
clrf HIGL
movlw b'10010001'
movwf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'00010001'
movwf HIGL
movlw b'10010001'
movwf MIDL
movlw b'00010001'
movwf LOWL
clrf EXTL
call ShowCube
movlw b'00010001'
movwf HIGL
movlw b'00010001'
movwf MIDL
movlw b'00010001'
movwf LOWL
clrf EXTL
call ShowCube
movlw b'01110101'
movwf HIGL
movlw b'00010001'
movwf MIDL
movlw b'01110101'
movwf LOWL
movlw b'00010001'
movwf EXTL
call ShowCube
movlw b'01110101'
movwf HIGL
clrf MIDL
movlw b'01110101'
movwf LOWL
movlw b'00010001'
movwf EXTL
call ShowCube
movlw b'01110101'
movwf HIGL
movlw b'01100100'
movwf MIDL
movlw b'01110101'
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
movlw b'01111111'
movwf HIGL
movlw b'01100100'
movwf MIDL
movlw b'01111111'
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
movlw b'01111111'
movwf HIGL
movlw b'01100100'
movwf MIDL
movlw b'01111111'
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
movlw b'01111111'
movwf HIGL
movlw b'01100100'
movwf MIDL
movlw b'01111111'
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
decfsz BRIG
goto Pattern_buildframe_loop
goto IdleCube
;******** PATTERN TWO BARS ***************************
;
; Shows two spinning bars
;
;*****************************************************
Pattern_twobars
movlw 0x00
movwf BRIG
movlw 0x20
movwf TIME
Pattern_twobars_loop:
movlw b'01000000'
movwf HIGL
movwf MIDL
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
movlw b'00001010'
movwf HIGL
movwf MIDL
movwf LOWL
clrf EXTL
call ShowCube
movlw b'00100100'
movwf HIGL
movwf MIDL
movwf LOWL
clrf EXTL
call ShowCube
movlw b'00010001'
movwf HIGL
movwf MIDL
movwf LOWL
clrf EXTL
call ShowCube
decfsz BRIG
goto Pattern_twobars_loop
goto IdleCube
;******** PATTERN UPDOWN *****************************
;
; Shows a layer moving up and down.
;
;*****************************************************
Pattern_updown:
movlw 0x00
movwf BRIG
movlw 0x50
movwf TIME
goto Pattern_treble_loop
;******** PATTERN TREBLE *****************************
;
; Shows a fast flickering cube
;
;*****************************************************
Pattern_treble:
movlw 0x00
movwf BRIG
movlw 0x10
movwf TIME
Pattern_treble_loop:
movlw b'11111111'
movwf HIGL
clrf MIDL
clrf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
clrf HIGL
movlw b'11111111'
movwf MIDL
clrf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
clrf HIGL
clrf MIDL
movlw b'11111111'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
decfsz BRIG
goto Pattern_treble_loop
goto IdleCube
;******** PATTERN SNAKE *****************************
;
; Shows a snake running across the cube
;
;*****************************************************
Pattern_snake
movlw 0x00
movwf BRIG
movlw 0x30
movwf TIME
Pattern_snake_loop:
movlw b'10100010'
movwf HIGL
clrf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'00110010'
movwf HIGL
clrf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'01110000'
movwf HIGL
clrf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'01011000'
movwf HIGL
clrf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'01001100'
movwf HIGL
clrf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'00001101'
movwf HIGL
clrf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'00000101'
movwf HIGL
clrf MIDL
clrf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00000011'
movwf HIGL
clrf MIDL
clrf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
clrf MIDL
clrf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'00100000'
movwf MIDL
clrf LOWL
clrf EXTL
call ShowCube
movlw b'00100000'
movwf HIGL
movlw b'00100000'
movwf MIDL
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
movlw b'00100000'
movwf MIDL
movlw b'00110000'
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
clrf MIDL
movlw b'01110000'
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
clrf MIDL
movlw b'01011000'
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
clrf MIDL
movlw b'01001100'
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
clrf MIDL
movlw b'00001101'
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
movlw b'00000001'
movwf MIDL
movlw b'00000101'
movwf LOWL
clrf EXTL
call ShowCube
clrf HIGL
movlw b'00000001'
movwf MIDL
movwf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
clrf HIGL
movlw b'00000011'
movwf MIDL
clrf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00100010'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00110010'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'01110000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'01011000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'01001100'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000100'
movwf HIGL
movlw b'00001100'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000101'
movwf HIGL
movlw b'00000100'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000101'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00000011'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'00100000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00100000'
movwf HIGL
movlw b'00100000'
movwf MIDL
movlw b'00100000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00100000'
movwf MIDL
movlw b'00110000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'01110000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'01000000'
movwf MIDL
movlw b'01010000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'01000000'
movwf HIGL
movlw b'01000000'
movwf MIDL
movlw b'01000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'01010000'
movwf HIGL
movlw b'01000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'01110000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00110010'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00000010'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010010'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000001'
movwf LOWL
movlw b'00000011'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000101'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00001101'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'01001100'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'01000000'
movwf MIDL
movlw b'01001000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'01000000'
movwf HIGL
movlw b'01000000'
movwf MIDL
movlw b'01000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'01001000'
movwf HIGL
movlw b'01000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'11001000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'10001010'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
decfsz BRIG
goto Pattern_snake_loop
goto IdleCube
;******** PATTERN FOURFACE ***************************
;
; Shows four faces of the cube
;
;*****************************************************
Pattern_fourface
movlw 0x00
movwf BRIG
movlw 0x30
movwf TIME
Pattern_fourface_loop:
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'11111111'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
movlw b'01001100'
movwf HIGL
movlw b'01001100'
movwf MIDL
movlw b'01001100'
movwf LOWL
movlw b'00000000'
movwf EXTL
call ShowCube
movlw b'11111111'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'00100010'
movwf MIDL
movlw b'00100010'
movwf LOWL
movlw b'00010011'
movwf EXTL
call ShowCube
decfsz BRIG
goto Pattern_fourface_loop
goto IdleCube
;******** PATTERN RLPLANE ****************************
;
; Shows a raising-lowering horizontal plane
;
;*****************************************************
Pattern_rlplane
movlw 0x00
movwf BRIG
movlw 0x40
movwf TIME
Pattern_rlplane_loop:
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'11111111'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'01001100'
movwf MIDL
movlw b'10110011'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
movlw b'01001100'
movwf HIGL
movlw b'10010001'
movwf MIDL
movlw b'00100010'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
movlw b'11011101'
movwf HIGL
movlw b'00100010'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
movlw b'11111111'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'10110011'
movwf HIGL
movlw b'01001100'
movwf MIDL
movlw b'00000000'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'10010001'
movwf MIDL
movlw b'01001100'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00100010'
movwf MIDL
movlw b'11011101'
movwf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
movlw b'00000000'
movwf HIGL
movlw b'00000000'
movwf MIDL
movlw b'11111111'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
decfsz BRIG
goto Pattern_rlplane_loop
goto IdleCube
;******** PATTERN ROTATEPLANE ************************
;
; Shows a rotating plane
;
;*****************************************************
Pattern_rotplane
movlw 0x00
movwf BRIG
movlw 0x30
movwf TIME
Pattern_rotplane_loop:
clrf HIGL
movlw b'11111111'
movwf MIDL
clrf LOWL
movlw b'00000010'
movwf EXTL
call ShowCube
movlw b'00100010'
movwf HIGL
movlw b'10010001'
movwf MIDL
movlw b'01001100'
movwf LOWL
movlw b'00010000'
movwf EXTL
call ShowCube
movlw b'10010001'
movwf HIGL
movwf MIDL
movwf LOWL
clrf EXTL
call ShowCube
movlw b'01001100'
movwf HIGL
movlw b'10010001'
movwf MIDL
movlw b'00100010'
movwf LOWL
movlw b'00000001'
movwf EXTL
call ShowCube
decfsz BRIG
goto Pattern_rotplane_loop
goto IdleCube
END
 
Last edited:

Thread Starter

DonutChan

Joined Mar 3, 2019
33
As the others have observed, this code has some ..uh issues. The way it uses the interrupt is unconventional..

The interrupt is used as a beat detector that changes the displayed pattern on each beat. It works like this:

  • The interrupt input is connected to an analog circuit that asserts signals on the interrupt input as the music beats.
  • On a beat, that external interrupt is asserted and a new random pattern is selected by looking at the 3 LSbits of the free running timer and doing a conventional lookup and GOTO(!!) to one of 8 pattern routines.
  • A pattern runs for awhile then jumps back to IdleCube. "Jumps?", you say. Yep. The stack is allowed to just overflow as interrupts occur and wrap around and around.
  • So, the interrupt is used simply as an edge-triggered event that seizes control from the currently running pattern, or IDLE if the pattern completes, and jumps to a new one.
  • Before the jump, the interrupt flag is cleared and interrupt re-enabled so that on the next beat, the process can repeat.
  • The pattern action is performed by brute-force rather than have the patterns stored in tables with a little processing engine to spit out the LED patterns.

As a long time PIC programmer, I am both horrified and twinged with a bit of awe at the implementation. It is breathtakingly bad coding practice but it looks like it works. Amazingly enough, I've actually seen the stack-overflow construct used before in a troubled project I took over some many years ago. Who'd have thunk I'd see another one?

I wouldn't be too optimistic that you could port this to another PIC. As far as I know the stacks quit wrapping around years ago.

Fun stuff!

Ah.. unfortunate, I confirmed I'd recreate it for a project assignment, but I've no idea how to do it in a way that's not as messy as this ;;
 

JohnInTX

Joined Jun 26, 2012
4,787
Ah.. unfortunate, I confirmed I'd recreate it for a project assignment, but I've no idea how to do it in a way that's not as messy as this ;;
It doesn't have to be such a kludge. If you break it down you have:
A beat detector
A pattern generator
Timer(s) to time the pattern updates and how long the pattern runs before it times out and goes back to the idle pattern.
A way to immediately terminate the pattern updates or idle pattern .
Several sequential lists of the bit outputs that create a pattern - think arrays.
A method to select a 'random' pattern.
The PWM(s) for brightness.

The timers can be generated by counting off interrupts from some internal timer. As many as you want.
Sequential patterns can be done by storing the output bit patterns in an array. A timed routine (sequence processor) simply fetches the output patterns, writes to the port, sets a timer and waits. When the timer runs out, it bumps the index and outputs the next set of bits. When it gets to the end, it restarts from the beginning of the array. Multiple patterns are stored in multiple arrays and the pattern selection is performed by simply storing the address of the current array. Changing the array changes the pattern. In C you'd do it as an array of pointers to arrays of bit patterns.
Besides timing each step of the selected pattern, the sequence processor looks for 1) an indicator that a beat has been detected to change the pattern or 2)that the pattern has been going long enough without the next beat and it's time to go to IDLE.
The beat interrupt simply sets a flag to indicate that a beat has occurred. The sequence processor checks that flag and acts accordingly, clearing it when it changes patterns in response to the detected beat.

That's about all there is to it. The hardware is OK and you can copy the bit patterns from the existing code.

Give it some thought.
 
Top