-
Addressing multiple PORTs using one Variable
Hi All,
I need to address five ports conditionally according to the value of one variable.
I found some posts about this subject and hoped this thread would help, but unfortunately, it doesn't.
This a code extract of my current project where timing is crucial and I have to write down a lot of repeating lines of code since FOR/NEXT and GOTOs and GOSUBs take too much time (I'm driving five NeoPixel SW2812B strings with each 28 LEDs/Pixels).
Code:
' PIC 16F690 @20MHz
#CONFIG
__config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
#ENDCONFIG
TRISC = %00000000
DEFINE OSC 20
PortPin VAR PORTA.0
X VAR BYTE
X = 23 ' PORTC.7 - "PORTA.0[23]"
MAIN:
PORTC.7 = 1 ' OK, obviously will work but useless - just make shure the scope works too
'PORTA.0[23] = 1 ' OK but useless
'PORTA.0[X] = 1 ' No! Makes a blink in the scope and then stays LOW
'PORTA[X] = 1 ' No!, nothing happens, pin stays LOW
'PortPin[23] = 1 ' OK but useless
'PortPin[X] = 1 ' No!, nothing happens, pin stays LOW
'PortPin.0[X] = 1 ' No!, error message "Bad variable size modifier: .0"
'...
ASM
nop
nop
nop
ENDASM
PORTC.7 = 0 ' have this syntax for tests only here
ASM
nop
ENDASM
GOTO MAIN
END
How do I solve this please?
-
Re: Addressing multiple PORTs using one Variable
Code:
PORTA.0[X] = 1 ' No! Makes a blink in the scope and then stays LOW
works ok in your loop for me, although it is much slower , period goes from 3uS to 13uS
-
Re: Addressing multiple PORTs using one Variable
"Makes a blink in the scope and then stays LOW"
It will return to low if:
1. you force it somewhere in the program to return to low
2. you PIC is reset for some reason (Watchdog maybe, decoupling cap missing, etc).
Other than these, I see no way to behave like this.
Ioannis
-
Re: Addressing multiple PORTs using one Variable
Quote:
1. you force it somewhere in the program to return to low
2. you PIC is reset for some reason (Watchdog maybe, decoupling cap missing, etc).
All the code and fuses settings are here.
I soldered the crystal directly on the µC's pins, a 100nF cap is there...
Quote:
although it is much slower , period goes from 3uS to 13uS
Strange. The pulse should be 800ns (nano seconds).
Okay, I'll give it a try with another 16F690...
-
Re: Addressing multiple PORTs using one Variable
Not sure I understand....
Are you saying that this code works:
Code:
MAIN:
PORTA.0[23] = 1 ' OK but useless
ASM
nop
nop
nop
ENDASM
PORTC.7 = 0 ' have this syntax for tests only here
ASM
nop
ENDASM
GOTO MAIN
END
And this isn't:
Code:
X VAR BYTE
X = 23
MAIN:
PORTA.0[X] = 1 ' No! Makes a blink in the scope and then stays LOW
ASM
nop
nop
nop
ENDASM
PORTC.7 = 0 ' have this syntax for tests only here
ASM
nop
ENDASM
GOTO MAIN
END
The 16F690 has an ADC and comparators.
Many of the pins are analog. I don't see you setting them to digital mode. PortC.7 is, however, not one of the analog pins but since you're trying to "index" pins with a variable I suspect PortC.7 isn't the only pin you want to use.
/Henrik.
-
Addressing multiple PORTs using one Variable
Yes Henrik, you might be right.
Keen to keep the code snippet very (maybe too) short here, I removed all others register settings I have set in the original code.
I'll give it also a try...when I'm back from office.
-
2 Attachment(s)
Re: Addressing multiple PORTs using one Variable
not really the results i expected, more doubt on proteus ?
i only expected the period to change
Attachment 9692
Attachment 9693
-
Addressing multiple PORTs using one Variable
So Richard,
What is the idea now, then?
Is there any "clean" -meaning software- workaround?
If not, I'll have to make five small independant circuits to each drive his own NeoPixel string, five circuits controlled by a sixth one :o
BTW, here is how my circuit works with 1 single NeoPixel string.
https://youtube.com/shorts/4fZk9KT4V1M
...still in office now.
-
Re: Addressing multiple PORTs using one Variable
Are you displaying the same "information" on all 5 strings or calculating the "content" for each string on the fly as you go about updating them?
Reason I ask is that 5 strings times 28 LEDs times 3 bytes per LED equals 420 bytes and the 16F690 only has 256 bytes of RAM.
-
Addressing multiple PORTs using one Variable
It is (going to be) a four digits 7 "segments" (each segment is made up of four NeoPixels >> 4x7= 28 NeoPixels per string) wall clock.
The fifth segment is made of 2 or 4 four (not decided yet) NeoPixels and will serve as seconds separator/indicator.
Yes, each string will be uptated specifically, if I can say so.
By now, it all fits in my 16F690 nicely because I address the strings only once at the time or 1x28x3 bytes in total.
-
Re: Addressing multiple PORTs using one Variable
Can all the outputs be on the same port, preferably sequential?
-
Addressing multiple PORTs using one Variable
Quote:
Can all the outputs be on the same port, preferably sequential?
As Henrik pointed, I'm somehow limited in the number of bytes I can use to address the NeoPixel strings.
Because of the very narrow timings, I cannot use routines to address the strings repeatetely with GOTOs/FOR-NEXTs/GOSUBs and so on. For this reason, I have to write code to address 24 bits for one Pixel in a row and only here, I can repeat the routine with one of the previous mentionned commands. This to say there is not only a timing issue but it is also about code length or space in the PIC.
Having this limitations in mind, I started my project addressing one string at the time and I've got plenty of time to display a minute based clock. Since all strings use the same common code and therefore the same variables, I can only differentiate them using different ports.
So if you mean to have only one NeoPixel string made of (4 digits x 7 segments x 4 Pixels [or LEDs] x 3 bytes per Pixel) + (4 Pixels x 3 bytes per Pixel) = 348 bytes, I can't address them in an array, as far as I understand it.
But what do you have in mind, please?
-
Re: Addressing multiple PORTs using one Variable
There is an easier protocol for addressable LEDs. The APA102 that is not strict on timing.
https://learn.sparkfun.com/tutorials...okup-guide/all
Ioannis
-
Re: Addressing multiple PORTs using one Variable
Quote:
Having this limitations in mind, I started my project addressing one string at the time and I've got plenty of time to display a minute based clock. Since all strings use the same common code and therefore the same variables, I can only differentiate them using different ports.
a 16f690 has 3 ports A,B and C by different ports do you mean different pins ?
Can all the outputs be on the same port, preferably sequential?
ie RC0:4 OR RC3:7 or similar
-
Addressing multiple PORTs using one Variable
Yes, ports will be in a sequential order.
I'll be using ports:- Seconds: PORTC.3
- Minutes Units: PORTC.4
- Minutes Thenths: PORTC.5
- Hours Units: PORTC.6
- Hours Tenths: PORTC.7
16F690 has:
PORTA.0..5
PORTB.4..7
PORTC.0..7
-
Re: Addressing multiple PORTs using one Variable
By changing pinsel var you can select different portc pins
if you need the remaining portc pins then more code is needed
Code:
' PIC 16F690 @20MHz#CONFIG
__config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
#ENDCONFIG
TRISC = %00000000
DEFINE OSC 20
pinsel var byte
pinsel = 128 ; 64 FOR RC:6 32 FOR RC:5 ETC
MAIN:
PORTC = PORTC | pinsel
ASM
nop
nop
nop
ENDASM
PORTC = 0 ' have this syntax for tests only here
ASM
nop
ENDASM
GOTO MAIN
END
-
Re: Addressing multiple PORTs using one Variable
have you tried to light a rgb led strip with a 690 @20mHz yet ?
i have doubts that such a slow chip will do the deed
-
Re: Addressing multiple PORTs using one Variable
Quote:
Originally Posted by
richard
have you tried to light a rgb led strip with a 690 @20mHz yet ?
i have doubts that such a slow chip will do the deed
That's why I proposed APA102 chips. Not strict on the clock frequency.
Ioannis
-
Addressing multiple PORTs using one Variable
Quote:
have you tried to light a rgb led strip with a 690 @20mHz yet ?
Check this: https://youtu.be/YlgEs6JWzTg :wink:
-
1 Attachment(s)
Addressing multiple PORTs using one Variable
And here's the project's code for now.
-
Re: Addressing multiple PORTs using one Variable
Have not checked al of your code, but in the ***_B routine you include many time the same code. Why not insert it one time and then use GoSub to it? Better efficiency and memory usage.
Also I see you insist on using this difficult protocol. Consider the APA101 as it is less strict and can be used on slow MCUs
Ioannis
-
Addressing multiple PORTs using one Variable
I tried to not repeat the code and use GOTOs or GOSUBS but then, if I do so, the NeoPixel string won't work anymore.
Would the use of an alternative LED string as you mention sove the problem of the ports/code/timing?
I can change for another system but would you have a code snippet to help me started with APA102 please? I've never heard about this one before.h
-
Re: Addressing multiple PORTs using one Variable
Here is a copy of the Richards example.
Code:
'***************************************************************************
'* Name : ap102.pbp *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 10/11/2017 *
'* Version : 1.0 *
'* Notes : only tested on pic18 @64 MHZ *
'* : pic18f26k22
'***************************************************************************
#CONFIG
CONFIG FOSC = INTIO67
CONFIG PLLCFG = ON
CONFIG PRICLKEN = OFF
CONFIG FCMEN = OFF
CONFIG IESO = OFF
CONFIG PWRTEN = OFF
CONFIG BOREN = SBORDIS
CONFIG BORV = 190
CONFIG WDTEN = ON
CONFIG WDTPS = 32768
CONFIG CCP2MX = PORTC1
CONFIG PBADEN = OFF
CONFIG CCP3MX = PORTB5
CONFIG HFOFST = ON
CONFIG T3CMX = PORTC0
CONFIG P2BMX = PORTB5
CONFIG MCLRE = EXTMCLR
CONFIG STVREN = ON
CONFIG LVP = OFF
CONFIG XINST = OFF
CONFIG DEBUG = OFF
CONFIG CP0 = OFF
CONFIG CP1 = OFF
CONFIG CP2 = OFF
CONFIG CP3 = OFF
CONFIG CPB = OFF
CONFIG CPD = OFF
CONFIG WRT0 = OFF
CONFIG WRT1 = OFF
CONFIG WRT2 = OFF
CONFIG WRT3 = OFF
CONFIG WRTC = OFF
CONFIG WRTB = OFF
CONFIG WRTD = OFF
CONFIG EBTR0 = OFF
CONFIG EBTR1 = OFF
CONFIG EBTR2 = OFF
CONFIG EBTR3 = OFF
CONFIG EBTRB = OFF
#ENDCONFIG
led_num con 3
pixels var byte[led_num * 3]
pallet var byte[21]
apa_global VAR byte bank0 ;global level 0-31
bit_cnt VAR byte bank0
i VAR byte
k VAR byte
j VAR byte
goto overpix
asm
_showpix
movlw LOW _pixels
movwf FSR2L
movlw high _pixels
movwf FSR2H
movlw 4
movwf _bit_cnt
movlw 0
s_frame ;start frame 4x 00 bytes
bcf PIR1,SSPIF
movwf SSPBUF
stspi BTFSs PIR1,SSPIF
bra stspi
decf _bit_cnt
bnz s_frame
movlw _led_num
movwf _bit_cnt
n_led
movlw 0xe0
iorwf _apa_global,W
bcf PIR1,SSPIF
movwf SSPBUF ;global led frame
glspi BTFSs PIR1,SSPIF
bra glspi
movf POSTINC2 ,W ;blue
bcf PIR1,SSPIF
movwf SSPBUF
blspi BTFSs PIR1,SSPIF
bra blspi
movf POSTINC2 ,W ;green
bcf PIR1,SSPIF
movwf SSPBUF
gnspi BTFSs PIR1,SSPIF
bra gnspi
movf POSTINC2 ,W ;red
bcf PIR1,SSPIF
movwf SSPBUF
rdspi BTFSs PIR1,SSPIF
bra rdspi
decf _bit_cnt
bnz n_led
movlw _led_num /8 +1 ;find magic number of bytes for stop frame
movwf _bit_cnt
movlw 0
stop_frame ;send stop frame
bcf PIR1,SSPIF
movwf SSPBUF
stopspi BTFSs PIR1,SSPIF
bra stopspi
decf _bit_cnt
bnz stop_frame
return
endasm
overpix:
define OSC 64
OSCCON = %11110000
ANSELb = 0
ANSELA = 0
ANSELC = 0
SSPCON1=$20;
SSPSTAT=$40;
trisc=%11010111
apa_global=1
latb.0=1
trisb=%11111110
arraywrite pallet,[255,0,0 ,0,255,0 ,0,0,255, 255,255,0 ,255,0,255 ,0,255,255, 255,255,255]
k=0 ;colour index
j=0
gosub shuffle
aloop:
call showpix
gosub shuffle
pause 40
goto aloop
And a YouTube video here
https://www.youtube.com/watch?v=UYvC-hukz-0
Ioannis
-
1 Attachment(s)
Re: Addressing multiple PORTs using one Variable
the youtube link is a dud, but i take it that it works even though the timing is a little out of specs
Attachment 9695
-
Re: Addressing multiple PORTs using one Variable
try this 16 led strip on RC7
Code:
' PIC 16F690 @20MHz
#CONFIG
__config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
#ENDCONFIG
CLEAR
TRISC = %00000000
DEFINE OSC 20
pinsel var byte
RED var byte
GREEN var byte
BLUE var byte
px var byte
bt var byte
pc var byte
pinsel = 128
MAIN:
GREEN=128
asm
MOVLW 16
MOVWF _pc
_nxRby
MOVF _GREEN,W
movwf _px
MOVLW 8
movwf _bt
RLF _px,F
_nxRbt movf _pinsel,W
IORWF PORTC ,F
BTFSS STATUS,C
GOTO XXR
NOP
NOP
NOP
XXR CLRF PORTC
NOP
RLF _px,F
DECFSZ _bt,F
GOTO _nxRbt
MOVF _RED,W
movwf _px
MOVLW 8
movwf _bt
RLF _px,F
_nxGbt movf _pinsel,W
IORWF PORTC,F
BTFSS STATUS,C
GOTO XXG
NOP
NOP
NOP
XXG CLRF PORTC
NOP
RLF _px,F
DECFSZ _bt,F
GOTO _nxGbt
MOVF _BLUE,W
movwf _px
MOVLW 8
movwf _bt
RLF _px,F
_nxBbt movf _pinsel,W
IORWF PORTC ,F
BTFSS STATUS,C
GOTO XXB
NOP
NOP
NOP
XXB CLRF PORTC
NOP
RLF _px,F
DECFSZ _bt,F
GOTO _nxBbt
DECFSZ _pc,F
GOTO _nxRby
endasm
PAUSE 100
GOTO MAIN
-
Addressing multiple PORTs using one Variable
Here's the link for the video again.
https://youtu.be/YlgEs6JWzTg
Sorry, I'm not the YouTube expert so I hope it works now :o
-
Addressing multiple PORTs using one Variable
Quote:
Originally Posted by
richard
try this 16 led strip on RC7
Thank a lot Richard. I'll give it a try :wink:
-
Re: Addressing multiple PORTs using one Variable
I take it that's a fail. I'm not surprised, the simulator indicated that @20mHz a pic16f690 cannot to a conditional branch quickly enough for a "LOW" pulse for a ws2812
-
Re: Addressing multiple PORTs using one Variable
Now, that is a surprise to me. This is a simple task for a simulator to calculate. It knows clock rate, instruction cycle, why does it fail to make simple calculations?
Ioannis
-
Re: Addressing multiple PORTs using one Variable
Quote:
Now, that is a surprise to me. This is a simple task for a simulator to calculate. It knows clock rate, instruction cycle, why does it fail to make simple calculations?
the simulator correctly indicated that the code will not work right from the start, the TOH is just out of spec
the code provided was to hopefully prove the outcome one way or the other in real life.
i assume it failed since roger never replied and then went on to ask pic18 questions
-
1 Attachment(s)
Addressing multiple PORTs using one Variable
I finally made the proto with 5 µC: 1 master and 4 slaves....
Anyway, thanks a lot to all for your help :wink:
Attachment 9699
-
1 Attachment(s)
Addressing multiple PORTs using one Variable
And this is how it looks like for now.
Attachment 9700