|
|
View previous topic :: View next topic |
Author |
Message |
beaker404
Joined: 24 Jul 2012 Posts: 163
|
function execution time. |
Posted: Fri May 31, 2019 1:35 pm |
|
|
Touched on this in an earlier post, continuing on here,
using a TI ADS8584S 16 bit ADC in parallel data mode, so using the following function to convert the outputs to digital values:
datasheet: http://www.ti.com/lit/ds/symlink/ads8584s.pdf
Code: |
signed int16 ADS8584S_BUILD_CHANNEL_VALUE() {
signed int16 value=0;
//output_high(LED_BLINK);
if(input(ADC_D15) == 1) { // 32768
bit_set(value,15);
}
if(input(ADC_D14) == 1) {
bit_set(value,14);
}
if(input(ADC_D13) == 1) {
bit_set(value,13);
}
if(input(ADC_D12) == 1) {
bit_set(value,12);
}
if(input(ADC_D11) == 1) {
//value = value + 2048;
bit_set(value,11);
//value = value << 1;
}
if(input(ADC_D10) == 1) {
bit_set(value,10);
}
if(input(ADC_D9) == 1) {
bit_set(value,9);
}
if(input(ADC_D8) == 1) {
bit_set(value,8);
}
if(input(ADC_D7) == 1) {
bit_set(value,7);
}
if(input(ADC_D6) == 1) {
bit_set(value,6);
}
if(input(ADC_D5) == 1) {
bit_set(value,5);
}
if(input(ADC_D4) == 1) {
bit_set(value,4);
}
if(input(ADC_D3) == 1) {
bit_set(value,3);
}
if(input(ADC_D2) == 1) {
bit_set(value,2);
}
if(input(ADC_D1) == 1) {
bit_set(value,1);
}
if(input(ADC_D0) == 1) {
bit_set(value,0);
}
return value;
} // end BUILD_CHANNEL_VALUE() |
The problem is, at 64MHz clock speed, this function takes 15uS to execute. Time I do not have. Is there a way to speed it up or do differently? I have configured the inputs as FAST_IO.
Code: |
#USE FAST_IO(E)
SET_TRIS_E(0XFF); //All of Port E is FAST IO inputs.
#USE FAST_IO(F)
SET_TRIS_F(0XFF);
#USE FAST_IO(H)
SET_TRIS_H(0X00);
#USE FAST_IO(J)
SET_TRIS_J(0X00);
#USE FAST_IO(D)
SET_TRIS_D(0X4C);
|
shows the way I have all of my IO set up as FAST_IO.
Code: |
#DEFINE ADC_D0 PIN_E0 // LSb
#DEFINE ADC_D1 PIN_E1
#DEFINE ADC_D2 PIN_E2
#DEFINE ADC_D3 PIN_E3
#DEFINE ADC_D4 PIN_E4
#DEFINE ADC_D5 PIN_E5
#DEFINE ADC_D6 PIN_E6
#DEFINE ADC_D7 PIN_E7
#DEFINE ADC_D8 PIN_H6
#DEFINE ADC_D9 PIN_H7
#DEFINE ADC_D10 PIN_F2
#DEFINE ADC_D11 PIN_F3
#DEFINE ADC_D12 PIN_F4
#DEFINE ADC_D13 PIN_F5
#DEFINE ADC_D14 PIN_F6
#DEFINE ADC_D15 PIN_F7 // MSb
|
shows what port pins on the PIC I am using for data lines.
Code: |
#device PIC18f87k22
#include <18F87K22.h>
#fuses HSH, NOWDT, PUT, NOBROWNOUT, NOMCLR
#use delay(crystal=16M, clock=64M)
#use rs232(UART1, baud=57600, STREAM=SERIAL, errors)
|
above is how the PIC is set up.
using the UART1 vary rarely so it is not figured in my loop time.
any ideas or is it just the 8 bit core showing me down?
18F87K22 running at 64MHz
CCS 5.061
MPLAB 8.91
Windows 10 |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Fri May 31, 2019 2:07 pm |
|
|
Maybe instead of testing each individual pin and assigning each one individually, grab the whole port and assign it right to value. That way you are checking 3 ports rather than doing checking 16 pins. It might be faster but I don't know...
Code: | value = 0;
value |= input_e();
value |= (input_h() >> 6) << 8;
value |= (input_f() >> 2) << 10; |
I don't know if my bitwise math is right, but try something like this. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri May 31, 2019 2:09 pm |
|
|
Just put this together quick, but should be correct.
value = make16(input_f(),input_e());
bit_clear(value,8);
bit_clear(value,9);
if(input(PIN_H6)) bit_set(value,8);
if(input(PIN_H7)) bit_set(value,9); |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Fri May 31, 2019 2:17 pm |
|
|
Thanks all, Gaugeguy, pasted your code suggestion and it helped.
my execute time went down and decreased my acquisition loop time.
I was at 40KHz, now up to 71KHz.
still would like to get some more speed though.
one problem I think is doing the signed math, no way out of that right now.
also, if I average any data I have to sum with a signed INT32 so I suspect that is expensive as well. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Fri May 31, 2019 2:26 pm |
|
|
64Mhz=16MIPS.
15uSec is then just 240 instruction times.
Looking at your posted code, it should not take this long.
A quick test shows it doesn't. Just compiled the code. Put it into a chip at 64Mhz, and pulsed a line high before calling the routine and low after the
return.
4.5uSec between the line changing.
Sounds to me as if you perhaps have not actually got the PLL enabled
so the chip is only running at 16Mhz, not 64.... |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Fri May 31, 2019 2:29 pm |
|
|
Code: |
#fuses HSH, NOWDT, PUT, NOBROWNOUT, NOMCLR
#use delay(crystal=16M, clock=64M)
|
I was thinking the above code let me run at 64MHz. Is there additional code to set the PLL?
I am using a 16MHz crystal and setting my clock to 64MHz. |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Fri May 31, 2019 8:13 pm |
|
|
According to the datasheet (Section 3.1):
The PLL is enabled by setting the PLLCFG bit (CON-FIG1H<4>) or the PLLEN bit (OSCTUNE<6>).
It looks like you will need to explicitly enable PLL. Both PLLEN and PLLCFG are disabled by default. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sat Jun 01, 2019 1:39 am |
|
|
OK. You definitely seem to be 'off' by a factor of about 4. The question is
'why'?.
I am testing with:
Code: |
signed int16 temp;
SET_TRIS_E(0XFF);
SET_TRIS_F(0XFF);
SET_TRIS_H(0X00);
SET_TRIS_D(0X4C);
SET_TRIS_J(0X00);
output_high(PIN_A0); //diagnostic
temp=ADS8584S_BUILD_CHANNEL_VALUE();
output_low(PIN_A0); //second marker
|
And with a logic analyser, rather than the scope (more accurate), it gives
4.4uSec between the edges on the pulse.
Now tested with your compiler, and with your fuses:
Code: |
#include <18F87K22.h>
#fuses HSH, NOWDT, PUT, NOBROWNOUT, NOMCLR, NOXINST
#use delay(crystal=16M, clock=64M)
#use rs232(UART1, baud=57600, STREAM=SERIAL, errors)
|
The compiler is correctly setting the PLLEN fuse:
Code: |
Configuration Fuses:
Word 1: D215 VREGSLEEP INTRC_HP SOSC_DIG NOXINST HSH PLLEN FCMEN IESO
Word 2: 7C78 PUT NOBROWNOUT BORV18 ZPBORM NOWDT WDT1048576
Word 3: 0BF9 RTCOSC_T1 EXTADDRSFT ABW8 BW16 NOWAIT CCP2C1 ECCPE MSSPMSK7 NOMCLR
Word 4: 0091 STVREN BBSIZ2K NODEBUG
Word 5: C0FF NOPROTECT NOCPB NOCPD
Word 6: E0FF NOWRT NOWRTC NOWRTB NOWRTD
Word 7: 40FF NOEBTR NOEBTRB
|
If your serial is working, then it has to be running at 64MHz.
How are you measuring your 15uSec figure?.
The routine codes as:
Code: |
.................... signed int16 ADS8584S_BUILD_CHANNEL_VALUE(void) {
00004: CLRF 08
00006: CLRF 07
....................
.................... signed int16 value=0;
....................
....................
....................
.................... //output_high(LED_BLINK);
.................... if(input(ADC_D15) == 1) { // 32768
00008: BTFSS F85.7
0000A: BRA 000E
....................
.................... bit_set(value,15);
0000C: BSF 08.7
....................
.................... }
....................
.................... if(input(ADC_D14) == 1) {
0000E: BTFSS F85.6
00010: BRA 0014
....................
.................... bit_set(value,14);
00012: BSF 08.6
....................
.................... }
....................
.................... if(input(ADC_D13) == 1) {
00014: BTFSS F85.5
00016: BRA 001A
....................
.................... bit_set(value,13);
00018: BSF 08.5
....................
.................... }
....................
.................... if(input(ADC_D12) == 1) {
0001A: BTFSS F85.4
0001C: BRA 0020
....................
.................... bit_set(value,12);
0001E: BSF 08.4
....................
.................... }
....................
.................... if(input(ADC_D11) == 1) {
00020: BTFSS F85.3
00022: BRA 0026
....................
.................... //value = value + 2048;
.................... bit_set(value,11);
00024: BSF 08.3
.................... //value = value << 1;
.................... }
....................
.................... if(input(ADC_D10) == 1) {
00026: BTFSS F85.2
00028: BRA 002C
....................
.................... bit_set(value,10);
0002A: BSF 08.2
....................
.................... }
....................
.................... if(input(ADC_D9) == 1) {
0002C: BTFSS F87.7
0002E: BRA 0032
....................
.................... bit_set(value,9);
00030: BSF 08.1
....................
.................... }
....................
.................... if(input(ADC_D8) == 1) {
00032: BTFSS F87.6
00034: BRA 0038
....................
.................... bit_set(value,8);
00036: BSF 08.0
....................
.................... }
....................
.................... if(input(ADC_D7) == 1) {
00038: BTFSS F84.7
0003A: BRA 003E
....................
.................... bit_set(value,7);
0003C: BSF 07.7
....................
.................... }
....................
.................... if(input(ADC_D6) == 1) {
0003E: BTFSS F84.6
00040: BRA 0044
....................
.................... bit_set(value,6);
00042: BSF 07.6
....................
.................... }
....................
.................... if(input(ADC_D5) == 1) {
00044: BTFSS F84.5
00046: BRA 004A
....................
.................... bit_set(value,5);
00048: BSF 07.5
....................
.................... }
....................
.................... if(input(ADC_D4) == 1) {
0004A: BTFSS F84.4
0004C: BRA 0050
....................
.................... bit_set(value,4);
0004E: BSF 07.4
....................
.................... }
....................
.................... if(input(ADC_D3) == 1) {
00050: BTFSS F84.3
00052: BRA 0056
....................
.................... bit_set(value,3);
00054: BSF 07.3
....................
.................... }
....................
.................... if(input(ADC_D2) == 1) {
00056: BTFSS F84.2
00058: BRA 005C
....................
.................... bit_set(value,2);
0005A: BSF 07.2
....................
.................... }
....................
.................... if(input(ADC_D1) == 1) {
0005C: BTFSS F84.1
0005E: BRA 0062
....................
.................... bit_set(value,1);
00060: BSF 07.1
....................
.................... }
....................
.................... if(input(ADC_D0) == 1) {
00062: BTFSS F84.0
00064: BRA 0068
....................
.................... bit_set(value,0);
00066: BSF 07.0
....................
.................... }
....................
.................... return value;
00068: MOVFF 07,01
0006C: MOVFF 08,02
00070: GOTO 00C2 (RETURN)
.................... }
|
Which is just 53 instructions. Allowing for the 16 BTFS instructions (which
take two machine cycles), we have 69 instruction times which at 16MIPS
is 4.3125uSec. Spot on.
So how are you measuring the 15uSec?. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Sat Jun 01, 2019 6:10 am |
|
|
Well my mistake, I call this function four times, once per channel. I am using a scope to time it. Y'all's calculations are correct, factor of four off due to where I put my pin toggle, around ALL four calls.
Pic is running 64MHz and my serial does work so sorry for the confusion. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sat Jun 01, 2019 7:39 am |
|
|
Calling it four times rather explains things...
Well, as you can see, it is just 53 instructions. Won't be faster on a 16bit
processor (nothing here uses things like 16bit arithmetic). Only thing
that will make it faster is clock rate. Normal DsPIC's have versions going
to 70MIPS. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|