Author Topic: PIC interrupt / data access not working  (Read 1450 times)

0 Members and 1 Guest are viewing this topic.

Offline Raven LuniTopic starter

  • Contributor
  • Posts: 18
  • Country: scotland
PIC interrupt / data access not working
« on: July 23, 2018, 09:10:18 pm »
Greetings,

I'm attempting to make an aquarium light with some neopixels but part of the code refuses to work and it's got me stumped.

What it does: Uses a PIC16F88 to drive a strip of 21 neopixels.  There are 7 settings, the first 4 are plain white decreasing in brightness, the other 3 are shimmer effects which are achieved by scrolling colours copied from the data memory.  This is the part which doesnt work.  Everything else works as expected but the 3 later settings do nothing (just appear to be a copies of setting 4)

It uses the TMR2 interrupt and polls for a button press on RA0 to change the setting.  This works.  The neopixel code works (since it displays the solid white values).  For some reason its either not copying the data memory contents to the 'screen memory' (pointed at by FSR) or its not calling the display function (f1_main) from the interrupt.  I cant find anything wrong with the code there so maybe another set of eyes might spot something.  Here is the code (uses my own assembler but shouldnt be too different from mainstream ones):


Code: [Select]
; =======================================
; Aquarium Light v0.1
; (c) 2018 Peter Hanratty
; =======================================

include f:\picprog\lib\pic16f88_reg.inc

; ---------------------------------------

equ func_count 7

equ pix_numlights 21
equ pix_numbytes 63

; ---------------------------------------

equ screen_addr 20h

equ pix_g 70h
equ pix_r 71h
equ pix_b 72h
equ pix_bits 73h
equ pix_bytes 74h

equ func_current 75h
equ func_select 76h

equ temp_s 77h
equ temp_d 78h
equ temp_c 79h
equ temp_b 7ah

; ---------------------------------------

; Reset and interrupt vectors

org 000h
goto init

; ---------------------------------------

org 004h

clrf status ; Bank 0
call f1_main

movf porta, w
movwf temp_b
btfss temp_b, 0
call changefunc
movf temp_b, w
xorlw 01h
movwf func_select

bcf pir1, 1
retfie

; =======================================

init:

; (dont) Set oscillator (HS, 16 MHz)
movlw 20h
movwf status ; Bank 1
clrf osccon

; Init PORTA (digital input)
clrf ansel
movlw ffh
movwf trisa

; Init PORTB (input, rb0=output)
movlw feh
movwf trisb
clrf status ; Bank 0
clrf portb

; Enable Interrupt
movlw c0h ; GIE, PEIE
movwf intcon
bsf status, 5 ; Bank 1
bsf pie1, 1 ; TMR2IE

; Set up TMR2
bcf pr2, 7 ; PR2 = 7fh
clrf status ; Bank 0
movlw 09h ; Pre:4, Post:16, Off
movwf t2con

; Init first function
clrf func_current
incf func_current, f
clrf func_select
call f1_init

; Start TMR2
bsf t2con, 2

goto main

; =======================================

changefunc:

btfsc func_select, 0
return

incf func_current, f
btfss func_current, 3
goto f1_init
movlw 1
movwf func_current
goto f1_init

; =======================================

fillstrip:
movlw screen_addr
movwf fsr
movlw pix_numlights
movwf pix_bytes

fillmem:
movf pix_g, w
movwf indf
incf fsr, f
movf pix_r, w
movwf indf
incf fsr, f
movf pix_b, w
movwf indf
incf fsr, f
decfsz pix_bytes, f
goto fillmem

return

; =======================================

colshuffle: ; shuffle pixels along

movlw 3
sublw pix_numbytes
movwf temp_c
addlw screen_addr
movwf temp_s
addlw 3
movwf temp_d
decf temp_s, f
decf temp_d, f
movf temp_d, w
movwf fsr
movf indf, w
movwf pix_b
decf fsr, f
movf indf, w
movwf pix_r
decf fsr, f
movf indf, w
movwf pix_g

colshuffle_loop:
movf temp_s, w
movwf fsr
movf indf, w
movwf temp_b
movf temp_d, w
movwf fsr
movf temp_b, w
movwf indf
decf temp_s, f
decf temp_d, f
decfsz temp_c, f
goto colshuffle_loop

movlw screen_addr
movwf fsr
movf pix_g, w
movwf indf
incf fsr, f
movf pix_r, w
movwf indf
incf fsr, f
movf pix_b, w
movwf indf

return

; =======================================

showpixels: ; Shift out pixel information
; Cycles: 19 per pixel + 35

movlw screen_addr
movwf fsr
movlw pix_numbytes
movwf pix_bytes

showbyte:
movlw 8
movwf pix_bits
movf indf, w
movwf temp_s

showbit:
btfsc temp_s, 7
goto highbit
nop
bsf portb, 0
bcf portb, 0
goto nextbit
highbit:
bsf portb, 0
nop
nop
bcf portb, 0
nextbit:
rlf temp_s, f
decfsz pix_bits, f
goto showbit

incf fsr, f
decfsz pix_bytes, f
goto showbyte

;movlw 10
;movwf temp_s
;pixwait: ; Delay for screen update
;decfsz temp_s, f
;goto pixwait

return

; =======================================

f1_init:

movf func_current, w
movwf temp_s
movlw ffh
decfsz temp_s, f
goto f2_init
goto f1_4_init

; ---------------------------------------

f2_init:

movlw c0h
decfsz temp_s, f
goto f3_init
goto f1_4_init

; ---------------------------------------

f3_init:

movlw 80h
decfsz temp_s, f
goto f4_init
goto f1_4_init

; ---------------------------------------

f4_init:

movlw 40h
decfsz temp_s, f
goto f5_init
goto f1_4_init

; ---------------------------------------

f5_init:

clrw
decfsz temp_s, f
goto f6_init
goto f5_7_init

; ---------------------------------------

f6_init:

addlw pix_numbytes
decfsz temp_s, f
goto f7_init
goto f5_7_init

; ---------------------------------------

f7_init:

addlw pix_numbytes
goto f5_7_init

; ---------------------------------------

f1_4_init:

movwf pix_g
movwf pix_r
movwf pix_b
call fillstrip
call showpixels
return

; ---------------------------------------

f5_7_init:

bsf status, 6 ; Bank 2
movwf eeadr
movlw screen_addr
movwf fsr
movlw pix_numbytes
movwf temp_c

f5_7_copy:
bsf status, 5 ; Bank 3
bcf eecon1, 7 ; Point to data memory
bsf eecon1, 0 ; Data memory read
bcf status, 5 ; Bank 2
movf eedata, w
movwf indf
incf eeadr, f
incf fsr, f
decfsz temp_c, f
goto f5_7_copy

clrf status ; Bank 0
return

; =======================================

f1_main:

movlw 5
subwf func_current, w
btfsc status, 0
return ; f1-4 = static light (do nothing)

f5_7_main:
call showpixels
call colshuffle
return

; =======================================

main:

nop
goto main

; =======================================


« Last Edit: July 23, 2018, 09:12:10 pm by Raven Luni »
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2085
Re: PIC interrupt / data access not working
« Reply #1 on: July 23, 2018, 09:35:07 pm »
First thing that appears odd is that you have not saved the "context" in your interrupt routine. Look at section 15.11 of the datasheet. Also, be careful with the "call"s - you have a very limited stack depth with the PICs.
 

Offline Raven LuniTopic starter

  • Contributor
  • Posts: 18
  • Country: scotland
Re: PIC interrupt / data access not working
« Reply #2 on: July 23, 2018, 09:38:08 pm »
All the code is called at the start or from the interrupt - the main loop is empty so no need to preserve anything
 

Offline Raven LuniTopic starter

  • Contributor
  • Posts: 18
  • Country: scotland
Re: PIC interrupt / data access not working
« Reply #3 on: July 23, 2018, 10:23:15 pm »
Could it be the way SUBWF affects the carry bit?  I've seen snippets here and there suggesting it might not set it as expected but nothing conclusive.  In f1_main I'm checking the current function by subtracting 5 and returning if the carry if set (which I would expect it to be if the current function is 4 or less).
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2085
Re: PIC interrupt / data access not working
« Reply #4 on: July 23, 2018, 10:31:52 pm »
I'd missed that! Unusual, but it should work.

Ok, try this:
If I've interpreted this correctly, and I'm not going put any money on it, - line 87 says:
Code: [Select]
movlw   09h             ; Pre:4, Post:16, Off
movwf   t2con
I make that "Pre 2, Post 16, Off". This gives you 1024 instruction cycles between interupts - that's pretty tight considering the number of bits that you have to bang-out.

 
The following users thanked this post: Raven Luni

Offline Raven LuniTopic starter

  • Contributor
  • Posts: 18
  • Country: scotland
Re: PIC interrupt / data access not working
« Reply #5 on: July 23, 2018, 10:47:04 pm »
Thanks - I'll change that to 4

Also confirmed that the problem is with the carry bit - by unplugging the data line and putting it back after a function change  (f1-4 should output once only and 5-7 continuously and it turns out to be the opposite so its otherwise all working - just cycling through an array of plain white values)

So changing
Code: [Select]
movlw 5
subwf func_current, w
btfsc status, 0
return

to

Code: [Select]
movlw 251
addwf func_current, w
btfss status, 0
return

should hopefully fix that.
Trap for young players as Dave would say :p
« Last Edit: July 23, 2018, 10:50:08 pm by Raven Luni »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf