PDA

View Full Version : Multiplexer address control..



retepsnikrep
- 19th July 2018, 08:24
I have a HTC4067 16x1 multiplexer, it's controlled by four lines S0, S1, S2, S3
I have these all connected to Port B pins 4,5,6,7 respectively on my pic. This could be reversed to 7,6,5,4 if that helps.
I'm after ideas on how to step through the input options 0-15 as per the truth table below as efficiently as possible.

i.e. select input 0, then 1, then 2 etc etc in sequence..

Increment a byte from 0 to 15 and mask off the 4 high bits?

Ideally I don't want to effect the output/status etc on the PortB 0,1,2,3 during this operation..

8739

pedja089
- 19th July 2018, 09:01
If you are using PIC 18F, then use simplest solution is
LATB.4=Control.0
LATB.5=Control.1
LATB.6=Control.2
LATB.7=Control.3

EDIT:
For PIC16

PortBCopy var byte

PortBCopy = PORTB
PortBCopy .4=Control.0
PortBCopy .5=Control.1
PortBCopy .6=Control.2
PortBCopy .7=Control.3
PORTB=PortBCopy

retepsnikrep
- 19th July 2018, 21:26
Yes thanks, but how to step through the options in the most efficient way without disturbing ports B0-3

pedja089
- 19th July 2018, 22:20
for control = 0 to 15
LATB.4=Control.0
LATB.5=Control.1
LATB.6=Control.2
LATB.7=Control.3
next control

Art
- 22nd July 2018, 15:59
It would be quicker if you used the port bits 0-3 instead, so you could just increment the port b value.
The quickest way also depends where the enable bit is connected.

Dave
- 22nd July 2018, 16:14
Pedja089, In your suggested code you are treating "Control" as an array. If it is not then you are just resetting the LATx bits 16 times.

pedja089
- 22nd July 2018, 17:28
I'm using as single bit, not array. And changing only upper 4 bit.
For this PBP will generate 4 asm instruction per PBP line, and execute 2 or 3 of them.
In worst case scenario 12 asm instruction are executed.
Compared to any PBP math function size, and speed are better in this case.
Maybe using logic you can get same result. You can try it if you want.
Let me explain little more...
Control=2
LATB.4=Control.0
LATB.5=Control.1
LATB.6=Control.2
LATB.7=Control.3
Bit 4 of LAT register is set to 0, bit 5 of LAT register is set to 1, bits 6,7 of LAT register is set to 0.
Bits 0,1,2,3, are unaffected.


PS
Array would be Control[i]...

Dave
- 22nd July 2018, 17:56
Pedja089, Why not just say:

for control = 0 to 15
LATB = LATB & $0F 'strip upper 4 bits
LATB = LATB | Control << 4 'add new control bits
next control

pedja089
- 23rd July 2018, 09:57
Because that would generate more than double ASM instructions. Lets compare ASM for your code and mine.

Here is your code

LATB = LATB & $0F 'strip upper 4 bits
LATB = LATB | Control << 4 'add new control bits
compiled:

Line Address Opcode Label DisAssy
468 03A6 0E0F Z00039 MOVLW 0xF
469 03A8 168A ANDWF LATB, F, ACCESS
470 03AA C03D Z0003A MOVFF Control, R0
471 03AC F013 NOP
472 03AE 6A14 CLRF 0x14, ACCESS
473 03B0 6A15 CLRF 0x15, ACCESS
474 03B2 6A16 CLRF 0x16, ACCESS
475 03B4 0E04 MOVLW 0x4
476 03B6 DEAE RCALL SHIFTL
477 03B8 6E23 MOVWF 0x23, ACCESS
478 03BA C014 MOVFF 0x14, 0x24
479 03BC F024 NOP
480 03BE C015 MOVFF 0x15, 0x25
481 03C0 F025 NOP
482 03C2 C016 MOVFF 0x16, 0x26
483 03C4 F026 NOP
484 03C6 5023 MOVF 0x23, W, ACCESS
485 03C8 128A IORWF LATB, F, ACCESS
If you look close there is RCALL SHIFTL.
Code for that:

Line Address Opcode Label DisAssy
139 0114 0FFF SHIFTL ADDLW 0xFF
140 0116 E2F9 BC shiftlloop
141 0118 5013 MOVF R0, W, ACCESS
142 011A EF8E GOTO 0x31C
143 011C F001 NOP
Then there is GOTO 0x31C
Code for that:

Line Address Opcode Label DisAssy
399 031C 0100 DUNN MOVLB 0x0
400 031E 0000 DUNN5 NOP
401 0320 0012 RETURN 0

Then there is also BC shiftlloop

Line Address Opcode Label DisAssy
134 010A 90D8 shiftlloop BCF STATUS, 0, ACCESS
135 010C 3613 RLCF R0, F, ACCESS
136 010E 3614 RLCF 0x14, F, ACCESS
137 0110 3615 RLCF 0x15, F, ACCESS
138 0112 3616 RLCF 0x16, F, ACCESS
139 0114 0FFF SHIFTL ADDLW 0xFF
140 0116 E2F9 BC shiftlloop
141 0118 5013 MOVF R0, W, ACCESS
142 011A EF8E GOTO 0x31C
143 011C F001 NOP

My code:

LATB.4=Control.0
LATB.5=Control.1
LATB.6=Control.2
LATB.7=Control.3
Compiled:


Line Address Opcode Label DisAssy
458 0392 B035 Z00039 BTFSC Control, 0, ACCESS
459 0394 888A BSF LATB, 4, ACCESS
460 0396 A035 BTFSS Control, 0, ACCESS
461 0398 988A BCF LATB, 4, ACCESS
462 039A B235 Z0003A BTFSC Control, 1, ACCESS
463 039C 8A8A BSF LATB, 5, ACCESS
464 039E A235 BTFSS Control, 1, ACCESS
465 03A0 9A8A BCF LATB, 5, ACCESS
466 03A2 B435 Z0003B BTFSC Control, 2, ACCESS
467 03A4 8C8A BSF LATB, 6, ACCESS
468 03A6 A435 BTFSS Control, 2, ACCESS
469 03A8 9C8A BCF LATB, 6, ACCESS
470 03AA B635 Z0003C BTFSC Control, 3, ACCESS
471 03AC 8E8A BSF LATB, 7, ACCESS
472 03AE A635 BTFSS Control, 3, ACCESS
473 03B0 9E8A BCF LATB, 7, ACCESS
in my code there is only 16 instruction. In worst case 12 is executed, in best case 8.
Can you calculate best and worse case for your code? Then compare it :)
This is depends lot of internal PBP optimization, and lib structure.
Another example is to use nested IFs instead of AND. Also I found way to use some temporally variable and single condition IF, and to get complex IFs that are fraction of size PBP's single line IF with multiple condition.
There is somewhere example on forum.
Same apply to math formula, tend to use single operation per line, and multiple lines...
Then compiler doesn't have to store bunch or intermediate results.
Sometimes less is more, and more is less.

If you write more lines of simple code then compiler have less to do. And tend to get better result(smaller code, less ram for lib's, faster execution times)

EDIT:
I'm using long, so there is little overhead like this
472 03AE 6A14 CLRF 0x14, ACCESS
473 03B0 6A15 CLRF 0x15, ACCESS
474 03B2 6A16 CLRF 0x16, ACCESS
to clear rest of R0 internal register.

Dave
- 23rd July 2018, 11:35
I didn't know we were going for speed....

richard
- 23rd July 2018, 12:47
or even this way, constant speed


control EQU 0x30
latb_shadow EQU 0x31
LATCH EQU 0x32 ; simulate lat reg


ORG ResetVector
goto Start


Start
MOVLW 0
MOVWF control
MOVLW 3
MOVWF LATCH ; eg. LATB,A
lopo
BANKSEL latb_shadow
INCF control,F
MOVLW 0xf
ANDWF control,F

MOVFF LATCH ,latb_shadow
MOVLW 0xf
andwf latb_shadow ,F
SWAPF latb_shadow,F
MOVF control,W
IORWF latb_shadow ,F
SWAPF latb_shadow,W
MOVWF LATCH

GOTO lopo

END

richard
- 24th July 2018, 07:59
A little more thought reduces it further,no need at all for a shadow working reg at all
works perfectly on the simulator steps through all 16 "control" states on latb 4-7 and preserves latb 0-3.


; TODO INSERT CONFIG CODE HERE USING CONFIG BITS GENERATOR
Processor 18f4550


include "p18f4550.inc"
TRUE equ 1
FALSE equ 0
cblock 0x30
control
;latb_shadow
endc


RES_VECT CODE 0x0000 ; processor reset vector
GOTO START ; go to beginning of program
; TODO ADD INTERRUPTS HERE IF USED
MAIN_PROG CODE ; let linker place main program
START






MOVLW 0f
MOVWF control
MOVLW 3
MOVWF LATB,A
lopo
BANKSEL control
INCF control,F
MOVLW 0xf
ANDWF control,F


MOVF LATB,A,W
ANDLW 0XF
SWAPF WREG,F
IORWF control,W
SWAPF WREG,F
MOVWF LATB ,A

GOTO lopo

Mike, K8LH
- 24th July 2018, 22:28
if I may...


RES_VECT CODE 0x0000 ; processor reset vector
GOTO START ; go to beginning of program
; TODO ADD INTERRUPTS HERE IF USED
MAIN_PROG CODE ; let linker place main program
START


MOVLW 0f
MOVWF control
MOVLW 3
MOVWF LATB,A
lopo
BANKSEL control
incf control,F ; control = control + 1
bcf control,4 ; control = control mod 15

swapf control,W ; B7..B4 <- control
xorwf LATB,W ; wreg = differences
andlw 0xF0 ; ignore B3..B0 bits
xorwf LATB,F ; update B7..B4 bits

GOTO lopo

Mike, K8LH
- 24th July 2018, 22:44
t'would be simpler/faster still if you were to use the B3..B0 pins as both the 'control' variable and 'control' I/O;


RES_VECT CODE 0x0000 ; processor reset vector
GOTO START ; go to beginning of program
; TODO ADD INTERRUPTS HERE IF USED
MAIN_PROG CODE ; let linker place main program
START


movlw 0x30 ; B7..B4 other I/O, B3..B0 = control
movwf LATB ;
lopo
incf LATB,W ; B3..B0 bits = control, 0..15
xorwf LATB,W ; wreg = differences
andlw 0x0F ; ignore B7..B4 bits (and control mod 16 for free)
xorwf LATB,F ; update B3..B0 bits, 0..15

GOTO lopo

richard
- 25th July 2018, 00:17
if I may...
Mike, K8LH

that's exactly what a good forum needs

your solution is excellent

Mike, K8LH
- 25th July 2018, 03:46
I like pedja089's solution which is probably about as simple, efficient, and elegant as you can get with pure PBP code. He might test clearing the four LATB bits and then setting them based on if control.0 = 1 then latb.4 = 1 (or something similar).

I have to say the code PBP generated for the "Control << 4" instruction was pretty dismal. I'm curious to see what XC8 will generate for that...

richard
- 25th July 2018, 04:14
I like pedja089's solution which is probably about as simple, efficient, and elegant as you can get with pure PBP code

it is simple but I wonder if it may cause some analog channel crosstalk effects when control inputs are changed sequentially like that esp at low clock speeds , just a thought.

Mike, K8LH
- 25th July 2018, 04:55
Oops! I didn't think of that...