View Full Version : Addressing multiple PORTs using one Variable
flotulopex
- 23rd July 2024, 17:06
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 (https://www.picbasic.co.uk/forum/showthread.php/1419-can-you-make-name-variables?p=7028) 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).
' 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?
richard
- 24th July 2024, 01:13
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
Ioannis
- 24th July 2024, 07:12
"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
flotulopex
- 24th July 2024, 10:03
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...
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...
HenrikOlsson
- 24th July 2024, 10:43
Not sure I understand....
Are you saying that this code works:
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:
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.
flotulopex
- 24th July 2024, 11:08
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.
richard
- 24th July 2024, 11:31
not really the results i expected, more doubt on proteus ?
i only expected the period to change
9692
9693
flotulopex
- 24th July 2024, 13:16
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.
HenrikOlsson
- 24th July 2024, 13:37
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.
flotulopex
- 24th July 2024, 13:43
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.
richard
- 24th July 2024, 14:22
Can all the outputs be on the same port, preferably sequential?
flotulopex
- 24th July 2024, 14:48
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?
Ioannis
- 24th July 2024, 17:06
There is an easier protocol for addressable LEDs. The APA102 that is not strict on timing.
https://learn.sparkfun.com/tutorials/apa102-addressable-led-hookup-guide/all
Ioannis
richard
- 25th July 2024, 00:44
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
flotulopex
- 25th July 2024, 07:39
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
richard
- 25th July 2024, 08:37
By changing pinsel var you can select different portc pins
if you need the remaining portc pins then more code is needed
' 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
richard
- 25th July 2024, 08:40
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
Ioannis
- 25th July 2024, 09:25
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
flotulopex
- 25th July 2024, 15:59
have you tried to light a rgb led strip with a 690 @20mHz yet ?
Check this:
https://youtu.be/YlgEs6JWzTg :wink:
flotulopex
- 25th July 2024, 16:03
And here's the project's code for now.
Ioannis
- 25th July 2024, 16:34
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
flotulopex
- 25th July 2024, 16:57
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
Ioannis
- 25th July 2024, 22:21
Here is a copy of the Richards example.
'************************************************* **************************
'* 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
richard
- 26th July 2024, 00:06
the youtube link is a dud, but i take it that it works even though the timing is a little out of specs
9695
richard
- 26th July 2024, 00:10
try this 16 led strip on RC7
' 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
flotulopex
- 26th July 2024, 15:26
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
flotulopex
- 26th July 2024, 15:30
try this 16 led strip on RC7
Thank a lot Richard. I'll give it a try :wink:
richard
- 28th July 2024, 04:07
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
Ioannis
- 28th July 2024, 16:37
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
richard
- 29th July 2024, 01:49
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
flotulopex
- 4th August 2024, 17:59
I finally made the proto with 5 µC: 1 master and 4 slaves....
Anyway, thanks a lot to all for your help :wink:
9699
flotulopex
- 4th August 2024, 18:01
And this is how it looks like for now.
9700
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.