PDA

View Full Version : Select case function



jackberg1
- 14th February 2025, 18:54
Hello everyone,

I'm looking for some tips, to enhance the code listed here to simplify with less code the "Select case'.

This code is for a PIC18F25K22 using PortC as a 64 switches matrix scan and PortB as the receiver and decoder and PortA to send the data.

Thanks for any comments.



' PIC18F25K22 64 Keys Encoder
' File :"D:\PIC\PBP3\18F25K22\64 Keys Encoder\64 Keys Encoder.pbp"
' Date : Feb 13 2025
'
' WPUB : p152 PORTB only
' PORTA : Flags
' PORTB : Row Input
' PORTC : Column Out
;----[18F25K22 Hardware Configuration]------------------------------------------
#CONFIG
CONFIG FOSC = INTIO67 ; Internal oscillator block
CONFIG PLLCFG = ON ; Oscillator used directly
CONFIG PRICLKEN = OFF ; Primary clock can be disabled by software
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRTEN = OFF ; Power up timer disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 190 ; VBOR set to 1.90 V nominal
CONFIG WDTEN = ON ; WDT is always enabled. SWDTEN bit has no effect
CONFIG WDTPS = 32768 ; 1:32768
CONFIG CCP2MX = PORTC1 ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<5:0> pins are configured as digital I/O on Reset
CONFIG CCP3MX = PORTB5 ; P3A/CCP3 input/output is multiplexed with RB5
CONFIG HFOFST = ON ; HFINTOSC output and ready status are not delayed by the oscillator stable status
CONFIG T3CMX = PORTC0 ; T3CKI is on RC0
CONFIG P2BMX = PORTB5 ; P2B is on RB5
CONFIG MCLRE = INTMCLR ; MCLR pin enabled, RE3 input pin disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
CONFIG XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
CONFIG DEBUG = OFF ; Disabled
CONFIG CP0 = OFF ; Block 0 (000800-001FFFh) not code-protected
CONFIG CP1 = OFF ; Block 1 (002000-003FFFh) not code-protected
CONFIG CP2 = OFF ; Block 2 (004000-005FFFh) not code-protected
CONFIG CP3 = OFF ; Block 3 (006000-007FFFh) not code-protected
CONFIG CPB = OFF ; Boot block (000000-0007FFh) not code-protected
CONFIG CPD = OFF ; Data EEPROM not code-protected
CONFIG WRT0 = OFF ; Block 0 (000800-001FFFh) not write-protected
CONFIG WRT1 = OFF ; Block 1 (002000-003FFFh) not write-protected
CONFIG WRT2 = OFF ; Block 2 (004000-005FFFh) not write-protected
CONFIG WRT3 = OFF ; Block 3 (006000-007FFFh) not write-protected
CONFIG WRTC = OFF ; Configuration registers (300000-3000FFh) not write-protected
CONFIG WRTB = OFF ; Boot Block (000000-0007FFh) not write-protected
CONFIG WRTD = OFF ; Data EEPROM not write-protected
CONFIG EBTR0 = OFF ; Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ; Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ; Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ; Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
CONFIG EBTRB = OFF ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
#ENDCONFIG


define OSC 64 ' OSC 64Mhz
ANSELA = 0 ' Set all digital
ANSELB = 0 ' Set all digital
ANSELC = 0 ' Set all digital
WPUB = $FF ' Set Weak PullUP PORTB only


'CMCON0 = 7
TRISA = 000000 ' PORTA Key Output
TRISB = 111111 ' PORTB Intput Keypad Rows in
TRISC = 000000 ' PORTC Output Keypad Column out
TRISE = 001000 ' PORTE.3 MCLRE as input '1' other output '0'
OSCCON = $70 ' Internal OSC p:30
OSCTUNE = $40 ' for 64Mhz FOSC p:35


Latch1 var byte ' Latch1 Flag
Latch1 = 0


LRShift VAR BIT ' Shift Direction Flag
LRSHIFT = 0


TTL VAR WORD 'Key val
TTL = 0


TTLadd var word ' adding to PORTC val
ttladd = 0


PORTKey var byte ' Key data
portkey = 0


Baud var word ' Serout2 Baud Rate
Baud = 84
'Baud = 16468


PORTB = 0 ' PORTB set to 0 Keypad Row
PAUSE 10
PORTC = 000001 ' Keypad Column out to Row PORTB
PORTA.0 = 1 ' serial port = 1 'avoid random data'
PORTA.1 = 0 ' Data Available


MAIN: ' Main Routine


PAUSE 1 ' needed for PORTC > PORTB Data transfert
LATB = PORTB ' Needed to use the value of PORTB


' Output Data to PORTC
IF PORTB > 0 AND Latch1 = 0 THEN
Latch1 = 1
LATC = LATB
PAUSE 5


' prevent duplicate
IF PORTC = 1 THEN
TTLADD = 0
endif
IF PORTC = 2 THEN
TTLADD = 128
endif
IF PORTC = 4 THEN
TTLADD = 384
endif
IF PORTC = 8 THEN
TTLADD = 512
endif
IF PORTC = 16 THEN
TTLADD = 640
endif
IF PORTC = 32 THEN
TTLADD = 758
endif
IF PORTC = 64 THEN
TTLADD = 896
endif
IF PORTC = 128 THEN
TTLADD = 1024
endif
' prevent duplicate


TTL = TTLADD + PORTB


' Select PORTKkey val
Select Case ttl
case 1
portkey = 1 : goto P
case 2
portkey = 2 : goto P
case 4
portkey = 3 : goto P
case 8
portkey = 4 : goto P
case 16
portkey = 5 : goto P
case 32
portkey = 6 : goto P
case 64
portkey = 7 : goto P
case 128
portkey = 8 : goto P


case 129
portkey = 9 : goto P
case 130
portkey = 10 : goto P
case 132
portkey = 11 : goto P
case 136
portkey = 12 : goto P
case 144
portkey = 13 : goto P
case 160
portkey = 14 : goto P
case 192
portkey = 15 : goto P
case 256
portkey = 16 : goto P


case 385
portkey = 17 : goto P
case 386
portkey = 18 : goto P
case 388
portkey = 19 : goto P
case 392
portkey = 20 : goto P
case 400
portkey = 21 : goto P
case 416
portkey = 22 : goto P
case 448
portkey = 23 : goto P
case 512
portkey = 24 : goto P


case 513
portkey = 25 : goto P
case 514
portkey = 26 : goto P
case 516
portkey = 27 : goto P
case 520
portkey = 28 : goto P
case 528
portkey = 29 : goto P
case 544
portkey = 30 : goto P
case 576
portkey = 31 : goto P
case 640
portkey = 32 : goto P


case 641
portkey = 33 : goto P
case 642
portkey = 34 : goto P
case 644
portkey = 35: goto P
case 648
portkey = 36 : goto P
case 656
portkey = 37 : goto P
case 672
portkey = 38 : goto P
case 704
portkey = 39 : goto P
case 768
portkey = 40 : goto P


case 759
portkey = 41 : goto P
case 760
portkey = 42 : goto P
case 762
portkey = 43 : goto P
case 766
portkey = 44 : goto P
case 774
portkey = 45 : goto P
case 790
portkey = 46 : goto P
case 822
portkey = 47 : goto P
case 886
portkey = 48 : goto P


case 897
portkey = 49 : goto P
case 898
portkey = 50 : goto P
case 900
portkey = 51 : goto P
case 904
portkey = 52 : goto P
case 912
portkey = 53 : goto P
case 928
portkey = 54 : goto P
case 960
portkey = 55 : goto P
case 1024
portkey = 56 : goto P


case 1025
portkey = 57 : goto P
case 1026
portkey = 58 : goto P
case 1028
portkey = 59 : goto P
case 1032
portkey = 60 : goto P
case 1040
portkey = 61 : goto P
case 1056
portkey = 62 : goto P
case 1088
portkey = 63 : goto P
case 1152
portkey = 64 : goto P
end select
' Select PORTKkey val


P:
pause 10
PORTA.1 = 1 ' Data Available


'SEROUT2 PORTA.0,Baud,[dec3 LATC," PORTC Bin: ", bin8 LATC,13,10] ' SW PORTC Column to PORTB Row
'SEROUT2 PORTA.0,Baud,[dec3 LATB," PORTB Bin: ", bin8 LATB," DEC TTL : ",DEC5 TTL," BIN TTL: ",BIN16 TTL,13,10] ' SW PORTB Row from PORTC Column
sEROUT2 PORTA.0,Baud,[" PORTB Dec :",dec3 LATB," PORTB Bin: ", bin8 LATB," TTL Dec : ",DEC4 TTL," TTL Bin : ",BIN16 TTL," Port Key: ",dec2 portkey," Port Key Bin : ",bin8 portkey,13,10]


ENDIF


' Wait for Key Release
WHILE PORTB > 0
WEND


' Reset Flag
latch1 = 0 ' Latch1
PORTA.1 = 0 ' Data Available
LATC = 0 ' LATC
TTL = 0
pause 50 ' Debounce pause


' Shift Direction Flag
IF PORTC = 1 THEN
lrshift = 0
endif
IF PORTC = 128 THEN
lrshift = 1
endif


' Shift PORTC
if lrshift = 0 then
PORTC = PORTC << 1 ' Shift Left
endif
if lrshift = 1 then
PORTC = PORTC >> 1 ' Shift Right
ENDIF


goto main ' restart loop




0
9907

0
9908

Acetronics2
- 14th February 2025, 19:55
just need to keep ONE GoTo P @ the end of your Select case's after the End Select

your syntax is " not so good " :rolleyes:




' prevent duplicate

IF PORTC = 1 THEN
TTLADD = 0
endif

IF PORTC = 2 THEN
TTLADD = 128
endif

IF PORTC = 4 THEN
TTLADD = 384
endif


One more good reason to use " select case " ...

I think you should read carefully the select case page of your Holy Manual ... ( not a C Compiler manual ... )

jackberg1
- 14th February 2025, 20:12
does the Select function case has to read every case before end select , or it's getting out when found the right one

the Goto P it's there so when a case is match then Goto P, to avoid reading all the case

Acetronics2
- 14th February 2025, 21:57
does the Select function case has to read every case before end select , or it's getting out when found the right one

the Goto P it's there so when a case is match then Goto P, to avoid reading all the case

I think you should read carefully the select case page of your Holy Manual

richard
- 14th February 2025, 23:59
for a 8x8 keypad there are 64 possible results
that's an extraordinary convoluted way to get a result


why not


key var byte ; high nibble column low nibble row
if portb then 'look for a 1
key = ncd portb 'row look for a 1
key = key + (ncd portc )<<4
PORTA.1 = 1 ' Data Available
WHILE PORTB >0 :wend
endif

jackberg1
- 15th February 2025, 01:10
Thank you richard

the reason I had to add a value to the portc, was the fact in the 64 key matrix some code were duplicate.
so 2 different key had the same value.

I'll have to test this code.

9909

jackberg1
- 15th February 2025, 16:00
Hello Richard

by inverting portb / portc I found no duplicate

If I may ask, how to know the time it took from the start to end of a for/next loop or select case in a program


Many thanks for your support.




key = ncd portb 'row look for a 1
key = key + (ncd portc )<<4

HenrikOlsson
- 15th February 2025, 17:02
If I may ask, how to know the time it took from the start to end of a for/next loop or select case in a program
Depends on what's available. I usually just set a pin high at the start and low again at the end of the routine I want to measure and then look at the pin using a scope or logic analyzer. Another option is to use one of the hardware timers and send the result to the PC using whatever serial connection is available (DEBUG, SEROUT, HSEROUT) but for longer routines one has to be little bit careful as to not overflow the timer and therefor get misleading values.

/Henrik.

jackberg1
- 15th February 2025, 20:05
Thank you HenrikOlsson

This is a very usefull solution since I got on hand a logic analyzer + scope.

jackberg1
- 16th February 2025, 16:59
Hello HenrikOlsson,

I did some timing test for the 'Select case' for key # 1 ~ key # 64

case # 1 : 3.48us and the last of the case key # 64 : 134.9us

Thanks again for this clever trick.

Acetronics2
- 17th February 2025, 06:39
If I may ask, how to know the time it took from the start to end of a for/next loop or select case in a program


the PBP soft way : https://dt.picbasic.co.uk/CODEX/CodeTimer

jackberg1
- 17th February 2025, 16:21
Hello Richard,

I rewrote my keypad program with the NCD function that you recomended, that help a lot

I changed the column value to the range from 1 ~ 64 with this I'm able to get an

average of 10~12us for the data available output signal.

The project served as a replacement of the old MM74C922/3.

Thanks again Richard for your great help.




' PIC18F25K22 64 Keys Encoder
' File : "D:\PIC\PBP3\18F25K22\64 Keys Encoder\64 Keys Encoder V2.pbp"
' Date : Feb 16 2025
' Benchmark : PortKey 1~64:~12us
' Used : 543 bytes
' WPUB : p152 PORTB only
' PORTA : Data Available D/A PORTA.7:High
' PORTB : Row Input
' PORTC : Column Output
'----[18F25K22 Hardware Configuration]------------------------------------------
#CONFIG
CONFIG FOSC = INTIO67 ; Internal oscillator block
CONFIG PLLCFG = ON ; Oscillator multiplied by 4
CONFIG PRICLKEN = OFF ; Primary clock can be disabled by software
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRTEN = OFF ; Power up timer disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 190 ; VBOR set to 1.90 V nominal
CONFIG WDTEN = OFF ; Watch dog timer is always disabled. SWDTEN has no effect.
CONFIG WDTPS = 32768 ; 1:32768
CONFIG CCP2MX = PORTC1 ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<5:0> pins are configured as digital I/O on Reset
CONFIG CCP3MX = PORTB5 ; P3A/CCP3 input/output is multiplexed with RB5
CONFIG HFOFST = ON ; HFINTOSC output and ready status are not delayed by the oscillator stable status
CONFIG T3CMX = PORTC0 ; T3CKI is on RC0
CONFIG P2BMX = PORTB5 ; P2B is on RB5
CONFIG MCLRE = INTMCLR ; RE3 input pin enabled; MCLR disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
#ENDCONFIG


define OSC 64 ' OSC 64Mhz
ANSELA = 0 ' Set all digital
ANSELB = 0 ' Set all digital
ANSELC = 0 ' Set all digital
'WPUB = $FF ' Set Weak PullUP PORTB only
'CMCON0 = 7
TRISA = 000000 ' PORTA Key Data available output
TRISB = 111111 ' PORTB Intput Keypad Rows in
TRISC = 000000 ' PORTC Output Keypad Column out
TRISE = 001000 ' PORTE.3 MCLRE as input '1' other output '0'
OSCCON = $70 ' Internal OSC p:30
OSCTUNE = $40 ' for 64Mhz FOSC p:35


' Var for Key & Port
Latch1 var byte ' Latch1 Flag
Latch1 = 0
LRShift VAR BIT ' Shift Direction Flag
LRSHIFT = 0


NCDB VAR BYTE ' NCD PORTB
NCDC VAR BYTE ' NCD PORTC


PORTKey var byte ' Key# data
portkey = 0


' Serial Terminal
Baud var word ' Serout2 Baud Rate
Baud = 84
'Baud = 16468


PAUSE 100
PORTC = 000001 ' Keypad Column out to Row PORTB
PORTA.7 = 0 ' Data Available
PORTB = 000000 ' PORTB set to 0 Keypad Row


MAIN: ' Main Routine


' Output Data to PORTC
IF PORTB > 0 AND Latch1 = 0 THEN
Latch1 = 1
'PORTA.1 = 1 ' Benchmark


' Get bit position 1~8
NCDB = NCD PORTB ' PORTB Row 'in'
NCDC = NCD PORTC ' PORTC Column 'out'


' Assign new value for PORTC Column
SELECT CASE NCDC
CASE 1
NCDC = 0
CASE 2
NCDC = 8
CASE 3
NCDC = 16
CASE 4
NCDC = 24
CASE 5
NCDC = 32
CASE 6
NCDC = 40
CASE 7
NCDC = 48
CASE 8
NCDC = 56
END SELECT

PORTKey = NCDC + NCDB ' Key# Data 1~64
PORTA = PORTKEY ' Data output
pause 1 ' Mandatory pause > 0 for PORTA to set
PORTA.7 = 1 ' Data available
'sEROUT2 PORTA.0,Baud,[" PORTB NCD: ",dec1 NCDB," PORTC NCD:",DEC1 NCDC," PORTKey :",DEC2 PORTKey,13,10]
ENDIF


' Wait for Key Release
WHILE PORTB > 0
WEND
pause 5 ' Key release debounce


' Reset Flag
latch1 = 0 ' Latch1
PORTA.7 = 0 ' Data available
PORTA.1 = 0 ' Benchmark
PORTKey = 0


' Shift Direction Flag
IF PORTC = 1 THEN
lrshift = 0
endif
IF PORTC = 128 THEN
lrshift = 1
endif


' Shift PORTC
if lrshift = 0 then
PORTC = PORTC << 1 ' Shift Left
endif
if lrshift = 1 then
PORTC = PORTC >> 1 ' Shift Right
ENDIF
PAUSE 1 ' Mandatory pause > 0 wait for Shift to set
goto main ' restart loop

Ioannis
- 17th February 2025, 18:46
With these errors, I think it cannot work...

Have marked with red the errors.

You should use percent character followed by binary values.

Ioannis




' PIC18F25K22 64 Keys Encoder
' File : "D:\PIC\PBP3\18F25K22\64 Keys Encoder\64 Keys Encoder V2.pbp"
' Date : Feb 16 2025
' Benchmark : PortKey 1~64:~12us
' Used : 543 bytes
' WPUB : p152 PORTB only
' PORTA : Data Available D/A PORTA.7:High
' PORTB : Row Input
' PORTC : Column Output
'----[18F25K22 Hardware Configuration]------------------------------------------
#CONFIG
CONFIG FOSC = INTIO67 ; Internal oscillator block
CONFIG PLLCFG = ON ; Oscillator multiplied by 4
CONFIG PRICLKEN = OFF ; Primary clock can be disabled by software
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRTEN = OFF ; Power up timer disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 190 ; VBOR set to 1.90 V nominal
CONFIG WDTEN = OFF ; Watch dog timer is always disabled. SWDTEN has no effect.
CONFIG WDTPS = 32768 ; 1:32768
CONFIG CCP2MX = PORTC1 ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<5:0> pins are configured as digital I/O on Reset
CONFIG CCP3MX = PORTB5 ; P3A/CCP3 input/output is multiplexed with RB5
CONFIG HFOFST = ON ; HFINTOSC output and ready status are not delayed by the oscillator stable status
CONFIG T3CMX = PORTC0 ; T3CKI is on RC0
CONFIG P2BMX = PORTB5 ; P2B is on RB5
CONFIG MCLRE = INTMCLR ; RE3 input pin enabled; MCLR disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
#ENDCONFIG


define OSC 64 ' OSC 64Mhz
ANSELA = 0 ' Set all digital
ANSELB = 0 ' Set all digital
ANSELC = 0 ' Set all digital
'WPUB = $FF ' Set Weak PullUP PORTB only
'CMCON0 = 7
TRISA = 000000 ' PORTA Key Data available output
TRISB = 111111 ' PORTB Intput Keypad Rows in
TRISC = 000000 ' PORTC Output Keypad Column out
TRISE = 001000 ' PORTE.3 MCLRE as input '1' other output '0'
OSCCON = $70 ' Internal OSC p:30
OSCTUNE = $40 ' for 64Mhz FOSC p:35


' Var for Key & Port
Latch1 var byte ' Latch1 Flag
Latch1 = 0
LRShift VAR BIT ' Shift Direction Flag
LRSHIFT = 0


NCDB VAR BYTE ' NCD PORTB
NCDC VAR BYTE ' NCD PORTC


PORTKey var byte ' Key# data
portkey = 0


' Serial Terminal
Baud var word ' Serout2 Baud Rate
Baud = 84
'Baud = 16468


PAUSE 100
PORTC = 000001 ' Keypad Column out to Row PORTB
PORTA.7 = 0 ' Data Available
PORTB = 000000 ' PORTB set to 0 Keypad Row


MAIN: ' Main Routine


' Output Data to PORTC
IF PORTB > 0 AND Latch1 = 0 THEN
Latch1 = 1
'PORTA.1 = 1 ' Benchmark


' Get bit position 1~8
NCDB = NCD PORTB ' PORTB Row 'in'
NCDC = NCD PORTC ' PORTC Column 'out'


' Assign new value for PORTC Column
SELECT CASE NCDC
CASE 1
NCDC = 0
CASE 2
NCDC = 8
CASE 3
NCDC = 16
CASE 4
NCDC = 24
CASE 5
NCDC = 32
CASE 6
NCDC = 40
CASE 7
NCDC = 48
CASE 8
NCDC = 56
END SELECT

PORTKey = NCDC + NCDB ' Key# Data 1~64
PORTA = PORTKEY ' Data output
pause 1 ' Mandatory pause > 0 for PORTA to set
PORTA.7 = 1 ' Data available
'sEROUT2 PORTA.0,Baud,[" PORTB NCD: ",dec1 NCDB," PORTC NCD:",DEC1 NCDC," PORTKey :",DEC2 PORTKey,13,10]
ENDIF


' Wait for Key Release
WHILE PORTB > 0
WEND
pause 5 ' Key release debounce


' Reset Flag
latch1 = 0 ' Latch1
PORTA.7 = 0 ' Data available
PORTA.1 = 0 ' Benchmark
PORTKey = 0


' Shift Direction Flag
IF PORTC = 1 THEN
lrshift = 0
endif
IF PORTC = 128 THEN
lrshift = 1
endif


' Shift PORTC
if lrshift = 0 then
PORTC = PORTC << 1 ' Shift Left
endif
if lrshift = 1 then
PORTC = PORTC >> 1 ' Shift Right
ENDIF
PAUSE 1 ' Mandatory pause > 0 wait for Shift to set
goto main ' restart loop

jackberg1
- 18th February 2025, 01:49
Thanks Ioannis for pointing this, the % are in fact on my program.
when uploading to the site something I select 'Courrier New' font append, and it's look they just vannish.
here's the upload.

'2nd upload seem to work fine this time'






' PIC18F25K22 64 Keys Encoder
' File : "D:\PIC\PBP3\18F25K22\64 Keys Encoder\64 Keys Encoder V2.pbp"
' Date : Feb 16 2025
' Benchmark : PortKey 1~64:~12us
' Used : 543 bytes
' WPUB : p152 PORTB only
' PORTA : Data Available D/A PORTA.7:High
' PORTB : Row Input
' PORTC : Column Output
'----[18F25K22 Hardware Configuration]------------------------------------------
#CONFIG
CONFIG FOSC = INTIO67 ; Internal oscillator block
CONFIG PLLCFG = ON ; Oscillator multiplied by 4
CONFIG PRICLKEN = OFF ; Primary clock can be disabled by software
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRTEN = OFF ; Power up timer disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 190 ; VBOR set to 1.90 V nominal
CONFIG WDTEN = OFF ; Watch dog timer is always disabled. SWDTEN has no effect.
CONFIG WDTPS = 32768 ; 1:32768
CONFIG CCP2MX = PORTC1 ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<5:0> pins are configured as digital I/O on Reset
CONFIG CCP3MX = PORTB5 ; P3A/CCP3 input/output is multiplexed with RB5
CONFIG HFOFST = ON ; HFINTOSC output and ready status are not delayed by the oscillator stable status
CONFIG T3CMX = PORTC0 ; T3CKI is on RC0
CONFIG P2BMX = PORTB5 ; P2B is on RB5
CONFIG MCLRE = INTMCLR ; RE3 input pin enabled; MCLR disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
#ENDCONFIG


define OSC 64 ' OSC 64Mhz
ANSELA = 0 ' Set all digital
ANSELB = 0 ' Set all digital
ANSELC = 0 ' Set all digital
'WPUB = $FF ' Set Weak PullUP PORTB only
'CMCON0 = 7
TRISA = %00000000 ' PORTA Key Data available output
TRISB = %11111111 ' PORTB Intput Keypad Rows in
TRISC = %00000000 ' PORTC Output Keypad Column out
TRISE = %00001000 ' PORTE.3 MCLRE as input '1' other output '0'
OSCCON = $70 ' Internal OSC p:30
OSCTUNE = $40 ' for 64Mhz FOSC p:35


' Var for Key & Port
Latch1 var byte ' Latch1 Flag
Latch1 = 0
LRShift VAR BIT ' Shift Direction Flag
LRSHIFT = 0


NCDB VAR BYTE ' NCD PORTB
NCDC VAR BYTE ' NCD PORTC


PORTKey var byte ' Key# data
portkey = 0


' Serial Terminal
Baud var word ' Serout2 Baud Rate
Baud = 84
PORTA.0 = 1 ' Avoid garbage on serial


PAUSE 100
PORTC = %00000001 ' Keypad Column out to Row PORTB
PORTA.7 = 0 ' Data Available
PORTB = %00000000 ' PORTB set to 0 Keypad Row


MAIN: ' Main Routine


' Output Data to PORTC
IF PORTB > 0 AND Latch1 = 0 THEN
Latch1 = 1

'PORTA.1 = 1 ' Benchmark


' Get bit position 1~8
NCDB = NCD PORTB ' PORTB Row 'in'
NCDC = NCD PORTC ' PORTC Column 'out'


' Assign new value for PORTC Column
SELECT CASE NCDC
CASE 1
NCDC = 0
CASE 8
NCDC = 56
CASE 2
NCDC = 8
CASE 7
NCDC = 48
CASE 3
NCDC = 16
CASE 6
NCDC = 40
CASE 4
NCDC = 24
CASE 5
NCDC = 32
END SELECT



PORTKey = NCDC + NCDB ' Key# Data 1~64
'PORTA = PORTKEY ' Data output


'PORTA.1 = 0 ' Benchmark


pause 2 ' Mandatory pause > 0 for PORTA to set

PORTA.7 = 1 ' Data available
sEROUT2 PORTA.0,Baud,[" PORTB NCD: ",dec1 NCDB," PORTC NCD:",DEC1 NCDC," PORTKey :",DEC2 PORTKey,13,10]
ENDIF


' Wait for Key Release
WHILE PORTB > 0
WEND
pause 5 ' Key release debounce


' Reset Flag
latch1 = 0 ' Latch1
PORTA.7 = 0 ' Data available
PORTKey = 0


' Shift Direction Flag
IF PORTC = 1 THEN
lrshift = 0
endif
IF PORTC = 128 THEN
lrshift = 1
endif



' Shift PORTC
if lrshift = 0 then
PORTC = PORTC << 1 ' Shift Left
endif
if lrshift = 1 then
PORTC = PORTC >> 1 ' Shift Right
ENDIF


PAUSE 1 ' Mandatory pause > 0 wait for Shift to set
goto main ' restart loop

jackberg1
- 19th February 2025, 17:48
This is the lasted update, some changes the 'Select case' as been move down

this alone is reducing the response time from 11us to 6us to the data available.

While the propagation time at the D/A of the MM74C922 is 60ns ~ 150ns max.

It will be hard to even get close to 500ns with the PIC18F25K22 unless someone has an idea to share.

I searched the internet for an affordable / alternative solution is to get into the CPLD or FPGA but it's not cost effective + VHDL learning process.

Any constructive comments is welcome.


9911

jackberg1
- 19th February 2025, 18:06
Here's the updated code (when using the '#" Wrap code, if I edit my post and save it, after the '%' or other characters are remove from the listing)

' PIC18F25K22 64 Keys Encoder V3
' File : "D:\PIC\PBP3\18F25K22\64 Keys Encoder\64 Keys Encoder V3.pbp"
' Date : Feb 19 2025
' Benchmark : PortKey 1~64: 3.988us ~ 6.25us
' Used : 621 bytes
' WPUB : p152 PORTB only
' PORTA : Data Available D/A PORTA.7:High
' PORTB : Row Input
' PORTC : Column Output
'----[18F25K22 Hardware Configuration]------------------------------------------
#CONFIG
CONFIG FOSC = INTIO67 ; Internal oscillator block
CONFIG PLLCFG = ON ; Oscillator multiplied by 4
CONFIG PRICLKEN = OFF ; Primary clock can be disabled by software
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRTEN = OFF ; Power up timer disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 190 ; VBOR set to 1.90 V nominal
CONFIG WDTEN = OFF ; Watch dog timer is always disabled. SWDTEN has no effect.
CONFIG WDTPS = 32768 ; 1:32768
CONFIG CCP2MX = PORTC1 ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<5:0> pins are configured as digital I/O on Reset
CONFIG CCP3MX = PORTB5 ; P3A/CCP3 input/output is multiplexed with RB5
CONFIG HFOFST = ON ; HFINTOSC output and ready status are not delayed by the oscillator stable status
CONFIG T3CMX = PORTC0 ; T3CKI is on RC0
CONFIG P2BMX = PORTB5 ; P2B is on RB5
CONFIG MCLRE = INTMCLR ; RE3 input pin enabled; MCLR disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
#ENDCONFIG


define OSC 64 ' OSC 64Mhz
ANSELA = 0 ' Set all digital
ANSELB = 0 ' Set all digital
ANSELC = 0 ' Set all digital
'WPUB = $FF ' Set Weak PullUP PORTB only
'CMCON0 = 7
TRISA = %00000000 ' PORTA Key Data available output
TRISB = %11111111 ' PORTB Intput Keypad Rows in
TRISC = %00000000 ' PORTC Output Keypad Column out
TRISE = %00001000 ' PORTE.3 MCLRE as input '1' other output '0'
OSCCON = $70 ' Internal OSC p:30
OSCTUNE = $40 ' for 64Mhz FOSC p:35


' Var for Key & Port
Latch1 var byte ' Latch1 Flag
Latch1 = 0
LRShift VAR BIT ' Shift Direction Flag
LRSHIFT = 0


NCDC VAR BYTE ' PORTC Bit Position 1~8
PORTKey var byte ' Key# data
portkey = 0


Baud var word ' Serout2 Baud Rate
Baud = 84


PORTA.0 = 1 ' Avoid random char on serial


PAUSE 100
PORTC = %00000001 ' Keypad Scan Column out to PORTB
PORTA.7 = 0 ' Data available / Benchmark
PORTB = %00000000 ' PORTB Keypad Row


MAIN: ' Main Routine


IF PORTB > 0 AND Latch1 = 0 THEN ' Detect Press Switch and Latch
Latch1 = 1


' PORTA.7 = 1 ' Benchmark Start


PORTKey = NCDC + NCD PORTB ' add bit position 1~8
'PORTA = PORTKEY ' Set PORTA / Disable for SEROUT2


' PORTA.7 = 0 ' Benchmark End


PAUSE 5 ' pause before D/A PORTA.7
PORTA.7 = 1 ' Data available / Disable for Benchmark


SEROUT2 PORTA.0,Baud,[" PORTB NCD: ",dec1 NCD PORTB," PORTC NCD:",DEC1 NCD PORTC," D/A PORTKey :",DEC2 PORTKey,13,10]
ENDIF


' Wait for Key Release
WHILE PORTB > 0
WEND
pause 5 ' Key release debounce


' Reset Flag
latch1 = 0 ' Latch1
PORTA.7 = 0 ' Data available after Key release
PORTKey = 0


' Shift Direction Flag
IF PORTC = 1 THEN
lrshift = 0
endif
IF PORTC = 128 THEN
lrshift = 1
endif

' Shift PORTC
if lrshift = 0 then
PORTC = PORTC << 1 ' Shift Left
endif
if lrshift = 1 then
PORTC = PORTC >> 1 ' Shift Right
ENDIF
PAUSEUS 20 ' pauseus wait for Shift to set


SELECT CASE NCD PORTC ' Assign new value for PORTC Column
CASE 1
NCDC = 0
CASE 8
NCDC = 56
CASE 2
NCDC = 8
CASE 7
NCDC = 48
CASE 3
NCDC = 16
CASE 6
NCDC = 40
CASE 4
NCDC = 24
CASE 5
NCDC = 32
END SELECT


goto main ' restart loop

jackberg1
- 19th February 2025, 18:42
While trying to correct my previous listing the 'Administrator is preventing me to edit after 30 minutes'

Dear Administrator read my previous post about the characters missing or changes after uploading to your site.

thank you

\ (when using the '#" Wrap code, if I edit my post and save it, after the '%' or other characters are remove from the listing

even some characters are show in lower case instead of upper case)\