PDA

View Full Version : Faster DIG algorithm



pedja089
- 12th February 2015, 23:18
Hi, I'm working on battery powered device. I need to extract 4 digits from word variable.
PORTA.4=1
TmpB=Pressure DIG 3
PORTA.4=0
Looking on my scope it takes 985uS to calculate digit.
TmpB=Pressure DIG 0 takes 245uS...
So for 4 digit it need 2.464mS.

ARRAYWRITE Str,[DEC4 Pressure]
This is little faster, it takes 2.295mS to execute. But I think it could be done faster...
Does anyone have idea how to implement it faster?
I'm goggling for algorithm...

Tabsoft
- 13th February 2015, 00:49
You can reduce the time a tiny bit by performing the operations manually, but just by a few Instruction cycles.

Here is what I ran in the MPLAB Simulator.
The times are listed for each method.



'************************************************* ***************
'* Name : DigTest.pbp *
'* Author : TABsoft *
'* Notice : Copyright (c) 2015 TABSoft *
'* : All Rights Reserved *
'* Date : 2/12/2015 *
'* Version : 1.0 *
'* Notes : PIC MCU @ 4MHz *
'* : *
'************************************************* ***************

'*****PIC MCU Configuration Fuses (MPASM)*****
#IF __PROCESSOR__ = "18F4620"
#CONFIG
CONFIG OSC = ECIO6 ; EC oscillator, port function on RA6
;CONFIG OSC = INTIO67 ; Internal oscillator block, port function on RA6 and RA7
;CONFIG WDT = OFF ; WDT disabled (control is placed on the SWDTEN bit)
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRT = OFF ; PWRT disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 3 ; Minimum setting
CONFIG WDT = ON ; WDT enabled
CONFIG WDTPS = 512 ; 1:512
CONFIG CCP2MX = PORTC ; CCP2 input/output is multiplexed with RC1
CONFIG PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
CONFIG LPT1OSC = OFF ; Timer1 configured for higher power operation
CONFIG MCLRE = ON ; 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 ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
CONFIG CP0 = OFF ; Block 0 (000800-003FFFh) not code-protected
CONFIG CP1 = OFF ; Block 1 (004000-007FFFh) not code-protected
CONFIG CP2 = OFF ; Block 2 (008000-00BFFFh) not code-protected
CONFIG CP3 = OFF ; Block 3 (00C000-00FFFFh) 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-003FFFh) not write-protected
CONFIG WRT1 = OFF ; Block 1 (004000-007FFFh) not write-protected
CONFIG WRT2 = OFF ; Block 2 (008000-00BFFFh) not write-protected
CONFIG WRT3 = OFF ; Block 3 (00C000-00FFFFh) 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-003FFFh) not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ; Block 3 (00C000-00FFFFh) 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
#else
#ERROR "This program requires a PIC 18F4620 MCU"
#endif

OSCCON = $60 ' Set PIC to 4Mhz & ECIO Clock Mode

DEFINE OSC 4
ADCON0.0 = 0 ' A/D Converter module is disabled
ADCON1 = $0F ' %0000 1111 AN2=VSS, AN3=VDD, AN12-0 = Digital
ADCON2 = $00 ' %0000 0000
TRISB = %11111111 ' Set PORTB as input
INTCON2.7 = 0 ' Enable PORTB pullups
TRISC = TRISC & %11011111 ' Set PORTC pin directions (pin5 output to RTC VCC2)


'*****Define LCD registers and bits*****
define LCD_BITS 4
define LCD_LINES 2 ' Set to number of lines for the LCD
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
define LCD_RWREG PORTE
define LCD_RWBIT 2
define LCD_COMMANDUS 1500
define LCD_DATAUS 44

pressure var word
tmpDig0 var byte
tmpDig1 var byte
tmpDig2 var byte
tmpDig3 var byte

'*****Initialize LCD*****
Low LATE.2 ' LCD R/W line low (W)
Pause 500 ' Wait .5 second for LCD to Initialize


main:
lcdout $fe,1
pressure = 1102

'Start Stopwatch in MPLAB Simulator
tmpDig0 = pressure dig 0
tmpDig1 = pressure dig 1
tmpDig2 = pressure dig 2
tmpDig3 = pressure dig 3
'Stop Stopwatch in MPLAB Simulator = 2962 Instruction Cycles @4MHz = 2.962ms (Fosc/4)

lcdout $fe,1,dec tmpDig3, dec tmpDig2, dec tmpDig1, dec tmpDig0
pause 500

'Start Stopwatch in MPLAB Simulator
tmpDig0 = pressure // 10
tmpDig1 = pressure / 10
tmpDig2 = pressure / 100
tmpDig3 = pressure / 1000

tmpDig1 = tmpDig1 // 10
tmpDig2 = tmpDig2 // 10
tmpDig3 = tmpDig3 // 10
'Stop Stopwatch in MPLAB Simulator = 2086 Instruction Cycles @4MHz = 2.086ms (Fosc/4)

lcdout $fe,$c0,dec tmpDig3, dec tmpDig2, dec tmpDig1, dec tmpDig0
pause 500
goto main
end

Acetronics2
- 13th February 2015, 08:45
Hi Pedja

DIG extracts ONE decimal digit ... ( here the 4 th )


I need to extract 4 digits from word variable.


what you are telling is not the same.

So, ... what exactly do you want to do ???

Alain

pedja089
- 13th February 2015, 09:47
/My english isn't good. Tabsoft got it right.
I'll try to explain better...
I have word variable Pressure.
I need to extract digits from Pressure variable to 4 different variables for displaying on static 7 segment LCD.
Offtopic:
To dive LCD just connect pin to pin LCD with MCU, and in ISR XOR LAT with mask every 20mS or so...
BANKSEL PORTA 'Select Bank
MOVLW 11101111b 'Mask unused pins
XORWF LATA,F 'Invert unmasked pins and write to LATA
It should have lower power consumption than multiplexed LCD wit LCD module on PIC.

Back to topic:
One thing that I tried is to use DIG and 4 variable. If I can extract one digit much faster, then do same thing for all 4 digits. That is why I ask for faster extracting for one variable...
Other way is to use arraywrite, and DEC4 to extract digit. Each byte in array will have one digit.

Tabsoft, thank you. You give me an idea:
Pressure = 1234
tmpDig0 = Pressure // 10 'tmpDig0 =4
pressure = Pressure / 10 'Pressure=123
tmpDig1 = Pressure // 10 'tmpDig1=3
pressure = Pressure / 10 'Pressure=12
tmpDig2 = Pressure // 10 'tmpDig2=2
tmpDig3 = Pressure / 10 'tmpDig3=1
This will be probably ok. It takes just under 1,5mS.
I didn't mention that I'm using PBPL and running on intosc at 16MHZ for all test.
I'm waiting boards to arrive, so I can't measure current consumption jet. So there is always option to go back to PBPW.

Thank you all.

Tabsoft
- 13th February 2015, 15:12
I confirmed you observations when I reran the routines @ 16MHz and PBPL.

I did notice if you use PBP's "DIG" command, the number of instruction cycles used are not consistent for various 4 digit numbers.

Here is the data I collected.




Algorithm 1:
Pressure = 1234
'Start Stopwatch in MPLAB Simulator
tmpDig0 = Pressure dig 0
tmpDig1 = Pressure dig 1
tmpDig2 = Pressure dig 2
tmpDig3 = Pressure dig 3
'Stop Stopwatch in MPLAB Simulator

Algorithm 2:
Pressure = 1234
'Start Stopwatch in MPLAB Simulator
tmpDig0 = Pressure // 10
tmpDig1 = Pressure / 10
tmpDig2 = Pressure / 100
tmpDig3 = Pressure / 1000

tmpDig1 = tmpDig1 // 10
tmpDig2 = tmpDig2 // 10
tmpDig3 = tmpDig3 // 10
'Stop Stopwatch in MPLAB Simulator

Algorithm 3:
Pressure = 1234
tmpDig0 = Pressure // 10
pressure = Pressure / 10
tmpDig1 = Pressure // 10
pressure = Pressure / 10
tmpDig2 = Pressure // 10
tmpDig3 = Pressure / 10
'Stop Stopwatch in MPLAB Simulator


PBPW @ 16MHz
Algorithm Inst Cycles Time
1 2958 739.50 us
2 2086 521.50 us
3 1783 445.75 us

PBPL @ 16MHz
Algorithm Inst Cycles Time
1 9626 2.406500 ms
2 6830 1.707500 ms
3 5839 1.459750 ms



Obviously PBPL slows down the routines considerably.

Good luck.

pedja089
- 13th February 2015, 15:32
Thanks.
I'll post current consumption when I get PCB.

ruijc
- 15th February 2015, 22:16
Hi guys,

This is an interesting topic.

I was wondering if the following line ( i dont know how fast it runs :mad: ) can also run faster with the technic shown above:


LCDOUT $FE,LINE2,"FREQ ",DEC DISPFREQ DIG 2,DEC DISPFREQ DIG 1,",",DEC DISPFREQ DIG 0, " KHz "

Best regards
Rui

Tabsoft
- 15th February 2015, 23:50
Yes, it will reduce the number of instruction cycles in your example.
Given that you are only extracting 3 digits of your DISPFREQ variable, Algorithm #2 will be faster.

Assuming you are using PBPW not PBPL here are the instruction cycles results.

Using the DIG method: 7606 Inst Cycles
Using Algorithm #2: 7293 Inst Cycles

That is a savings of 313 instruction cycles. If you are running a 4Mhz Fosc/4 MCU then that would be a 313us savings.
Though it is a small savings on cycles and time, it does come at a cost of 3 extra byte variables to hold the values.

Here are the two code options tested.



tmpDig0 var byte
tmpDig1 var byte
tmpDig2 var byte
DISPFREQ var byte
LINE2 con $c0


DISPFREQ = 1234

'Start Stopwatch in MPLAB Simulator
LCDOUT $FE,LINE2,"FREQ ",DEC DISPFREQ DIG 2,DEC DISPFREQ DIG 1,",",DEC DISPFREQ DIG 0, " KHz "
'Stop Stopwatch in MPLAB Simulator
'Output: FREQ 23,4 KHz

'Start Stopwatch in MPLAB Simulator
tmpDig0 = DISPFREQ // 10
tmpDig1 =DISPFREQ / 10
tmpDig1 = tmpDig1 // 10
tmpDig2 = DISPFREQ / 100
tmpDig2 = tmpDig2 // 10

LCDOUT $FE,LINE2,"FREQ ",DEC tmpDig2,DEC tmpDig1,",",DEC tmpDig0, " KHz "
'Stop Stopwatch in MPLAB Simulator
'Output: FREQ 23,4 KHz

ruijc
- 16th February 2015, 00:36
Greetings Tabsoft,

Thank you for the information and tip.
Very helpfull ! ;)

Regards
Rui