CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

is there an efficient way to write on a 16bit array item?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

is there an efficient way to write on a 16bit array item?
PostPosted: Sat Jul 06, 2019 6:02 pm     Reply with quote

18f25k40 v5.081
Hello guys, I have a problem with 16 bit array coding. I have 3 arrays and each of them have 256 16bit items. What I do is reading a pin and writing that to related array item then shifting bits. (reading ADC output and writing to variable one by one). But it takes too many instruction lines to complete, 21 lines for 1 read. it takes only 4 lines per read if I use a normal 16 bit variables instead of arrays but then if i define 756 16bit variables and write reading code 256 times (can't use for loops with unique variable names of course) then my ram gets full, so I can't compile the code. I need to learn a way to use arrays much efficient, anyone has any idea about it?

array output
Code:

........... sensor_data_1[pixel_pointer]|=input_state(ADC_outa); //read adc output

03BA:  BCF    FD8.0
03BC:  RLCF   1E,W
03BE:  MOVWF  02
03C0:  RLCF   1F,W
03C2:  MOVWF  03
03C4:  MOVF   02,W
03C6:  ADDLW  20
03C8:  MOVWF  FE9
03CA:  MOVLW  00
03CC:  ADDWFC 03,W
03CE:  MOVWF  FEA
03D0:  MOVLW  00
03D2:  BTFSC  F8E.6
03D4:  MOVLW  01
03D6:  IORWF  FEF,W
03D8:  MOVWF  00
03DA:  MOVFF  FEC,03
03DE:  MOVF   00,W
03E0:  MOVF   FED,F
03E2:  MOVWF  FEF
03E4:  MOVFF  03,FEC

variable output

Code:
........... sensor_data_1_0|=input_state(ADC_outa); //read adc output
0362:  MOVLW  00
0364:  BTFSC  F8E.6
0366:  MOVLW  01
0368:  IORWF  20,F


array shifting
Code:

............ sensor_data_1[pixel_pointer]=sensor_data_1[pixel_pointer]<<1; // shift data
0418:  BCF    FD8.0
041A:  RLCF   1E,W
041C:  MOVWF  02
041E:  RLCF   1F,W
0420:  MOVWF  03
0422:  MOVF   02,W
0424:  ADDLW  20
0426:  MOVWF  01
0428:  MOVLW  00
042A:  ADDWFC 03,F
042C:  MOVFF  03,627
0430:  BCF    FD8.0
0432:  RLCF   1E,W
0434:  MOVWF  02
0436:  RLCF   1F,W
0438:  MOVWF  03
043A:  MOVF   02,W
043C:  ADDLW  20
043E:  MOVWF  FE9
0440:  MOVLW  00
0442:  ADDWFC 03,W
0444:  MOVWF  FEA
0446:  MOVFF  FEC,629
044A:  MOVF   FED,F
044C:  MOVFF  FEF,628
0450:  BCF    FD8.0
0452:  RLCF   x28,W
0454:  MOVWF  02
0456:  RLCF   x29,W
0458:  MOVFF  627,FEA
045C:  MOVFF  01,FE9
0460:  MOVWF  FEC
0462:  MOVF   FED,F
0464:  MOVFF  02,FEF


Variable Shifting
Code:
....................          sensor_data_1_0=sensor_data_1_0<<1; //shift data
0374:  BCF    FD8.0
0376:  RLCF   20,F
0378:  RLCF   21,F

_________________
There is nothing you can't do if you try
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 07, 2019 3:48 am     Reply with quote

Post the lines that declare the arrays. You have posted the usage, but
not the declarations.

Your arrays:
sensor_data_1_0
sensor_data_1
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jul 07, 2019 4:36 am     Reply with quote

Yes, we need more information ! I'm GUESSING that you're reading data from a 16 by 16 bit RGB analog light sensor ? If you tell us the purpose of the program, we may be able to help with 'shortcuts' or other methods to capture/store/use the data.

Jay
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Sun Jul 07, 2019 5:27 am     Reply with quote

Hi, I just used standard array declaration so didn't think it would be needed. Here is declaration and function for reading.

Code:
volatile unsigned int16 pixel_pointer=0,sensor_data_1[256],sensor_data_2[256],sensor_data_3[256];.
.
.
.
.
void get_one_reading(void)
{
   /*  Enable sensor integrations  */
   output_bit(Sensor_dis1,0);
   output_bit(Sensor_dis2,0);
   output_bit(Sensor_dis3,0);
   /*  Start sensor integrations  */
   output_bit(Sensor_si1,1);
   output_bit(Sensor_si2,1);
   output_bit(Sensor_si3,1);
   delay_cycles(3); //give sime time for settling
   output_bit(Sensor_clk,1); //sensor clock signal high
   delay_cycles(2);
   output_bit(Sensor_clk,0); //sensor clock signal low
   /*  Close integration signal to prevent reset  */
   output_bit(Sensor_si1,0);
   output_bit(Sensor_si2,0);
   output_bit(Sensor_si3,0);
   /*  Data is ready at the output pin of sensor at the moment  */
   for(int16 pixel_counter=0;pixel_counter<256;pixel_counter++)
   {
      sensor_data_1[pixel_pointer]=0;
      sensor_data_2[pixel_pointer]=0;
      sensor_data_3[pixel_pointer]=0;
      output_bit(ADC_cs,0); //start adc conversion
      for(int i=0;i<14;i++)  //we will read 14 bits
      {
         output_bit(ADC_sclk,0); //send first clock signal to adc
         sensor_data_1[pixel_pointer]|=input_state(ADC_outa); //read adc output
         sensor_data_2[pixel_pointer]|=input_state(ADC_outb);
         output_bit(ADC_sclk,1);  //complete clock pulse
         sensor_data_1[pixel_pointer]=sensor_data_1[pixel_pointer]<<1; //shift data
         sensor_data_2[pixel_pointer]=sensor_data_2[pixel_pointer]<<1;     
      }
      output_bit(ADC_cs,1); //stop adc conversion
      output_bit(ADC_a1,1); //change adc input
      output_bit(ADC_cs,0); //start adc conversion
      for(int i=0;i<14;i++)  //we will read 14 bits
      {
         output_bit(ADC_sclk,0); //send first clock signal to adc
         sensor_data_3[pixel_pointer]|=input_state(ADC_outa); //read adc output
         output_bit(ADC_sclk,1);  //complete clock pulse
         sensor_data_3[pixel_pointer]=sensor_data_1[pixel_pointer]<<1; //shift data
      }
      output_bit(ADC_cs,1); //stop adc conversion
      output_bit(ADC_a1,0); //change adc input
      output_bit(Sensor_clk,1);
      delay_cycles(2);
      output_bit(Sensor_clk,0);
      pixel_pointer++;
   }
}


Program's purpose is pretty simple, I have 3 1x256 pixels analog light sensors and a fast adc, I trigger sensors and read outputs with adc then store them.
Thing is, reading adc output and storing them directly in array items tooks so much time and I want to avoid it.
But found a simple solution while I was writing this reply, reading outputs into a single variable and appointing it to a array item after 14 bit reading would help.
Still I wonder if I there is a way that I can do readings into an array item directly and much more efficiently.
_________________
There is nothing you can't do if you try
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 07, 2019 7:43 am     Reply with quote

Use the built-in CCS functions to do this. Example:
Code:
..... shift_left(&sensor_data_1[pixel_pointer], 2, 0);   
008A:  BCF    STATUS.C
008C:  RLCF   pixel_pointer,W
008E:  MOVWF  @02
0090:  RLCF   pixel_pointer+1,W
0092:  MOVWF  @03
0094:  MOVF   @02,W
0096:  ADDLW  sensor_data_1
0098:  MOVWF  @01
009A:  MOVLW  sensor_data_1+-6
009C:  ADDWFC @03,F
009E:  MOVFF  01,@@206
00A2:  MOVFF  03,@@207
00A6:  MOVFF  @@207,FSR0H
00AA:  MOVFF  @@206,FSR0L
00AE:  BCF    STATUS.C
00B0:  RLCF   INDF0,F
00B2:  RLCF   PREINC0,F
.................... 

The shift_left() function is in the CCS manual.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf

Test program:
Code:

#include <18F25K40.h>
#fuses NOWDT,PUT,BROWNOUT
#use delay(internal=4M)

unsigned int16 pixel_pointer=0,sensor_data_1[256];

//=================================
void main()
{
sensor_data_1[pixel_pointer] = sensor_data_1[pixel_pointer] << 1; 

shift_left(&sensor_data_1[pixel_pointer], 2, 0); 

while(TRUE);
}
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Sun Jul 07, 2019 3:59 pm     Reply with quote

Thanks for info PCM, i'll try for shifting, would you advice something more efficient for "sensor_data_1[pixel_pointer]|=input_state(ADC_outa);" too?
_________________
There is nothing you can't do if you try
sunitapr



Joined: 06 Aug 2019
Posts: 1
Location: Banned - spammer

View user's profile Send private message Visit poster's website

16-bit array
PostPosted: Tue Aug 06, 2019 12:24 am     Reply with quote

Thanks for sharing information. I will try this 16 bit array coding.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Aug 06, 2019 1:09 am     Reply with quote

There are some tricks to improve things a little, but the emphasis is on 'little'.
Problem is that as soon as you are involved in 'indirect addressing' (which
the 'array' implies), you are forced to be updating a pointer 'to' the data,
and transfers through the indirect addressing registers. Result much more
overhead. As an example though of how a little saving cam be made, compare the assembler from two different ways of accessing a 256word
array:
Code:

int16 demo[256];

void main(void)
{
   int16* ptr;
   int16 ctr;
   setup_adc_ports(sAN0);
   setup_adc(ADC_CLOCK_DIV_32 | ADC_TAD_MUL_8);
   //setup adc so Tacq is generated automatically

   while(TRUE)
   {
      //Compare the two approaches:
      for ( ctr=0;ctr<256;ctr++)
         demo[ctr]=read_adc(); //first standard array access
      ptr=demo;
      for (ctr=0;ctr<256;ctr++)
         *(ptr++)=read_adc(); //second using a pointer instead
   }
}

....................       for ( ctr=0;ctr<256;ctr++)
0054:  MOVLB  2
0056:  CLRF   x07
0058:  CLRF   x06
005A:  MOVF   x07,W
005C:  SUBLW  00
005E:  BTFSS  FD8.0
0060:  GOTO   009A
....................          demo[ctr]=read_adc();
0064:  BCF    FD8.0
0066:  RLCF   x06,W
0068:  MOVWF  02
006A:  RLCF   x07,W
006C:  MOVWF  03
006E:  MOVF   02,W
0070:  ADDLW  04
0072:  MOVWF  FE9
0074:  MOVLW  00
0076:  ADDWFC 03,W
0078:  MOVWF  FEA
007A:  BSF    F60.0
007C:  NOP   
007E:  BTFSC  F60.0
0080:  GOTO   007E
0084:  MOVFF  F64,03
0088:  MOVFF  F63,FEF
008C:  MOVFF  F64,FEC
0090:  INCF   x06,F
0092:  BTFSC  FD8.2
0094:  INCF   x07,F
0096:  GOTO   005A
....................       ptr=demo;
009A:  CLRF   x05
009C:  MOVLW  04
009E:  MOVWF  x04
....................       for (ctr=0;ctr<256;ctr++)
00A0:  CLRF   x07
00A2:  CLRF   x06
00A4:  MOVF   x07,W
00A6:  SUBLW  00
00A8:  BTFSS  FD8.0
00AA:  GOTO   00E6
....................          *(ptr++)=read_adc();
00AE:  MOVFF  205,03
00B2:  MOVFF  204,00
00B6:  MOVLW  02
00B8:  ADDWF  x04,F
00BA:  BTFSC  FD8.0
00BC:  INCF   x05,F
00BE:  MOVFF  00,FE9
00C2:  MOVFF  03,FEA
00C6:  BSF    F60.0
00C8:  NOP   
00CA:  BTFSC  F60.0
00CC:  GOTO   00CA
00D0:  MOVFF  F64,03
00D4:  MOVFF  F63,FEF
00D8:  MOVFF  F64,FEC
00DC:  INCF   x06,F
00DE:  BTFSC  FD8.2
00E0:  INCF   x07,F
00E2:  GOTO   00A4
00E6:  GOTO   0056


The 'ponter' version is three instructions shorter than the 'array' version.
The difference is that in the 'array' version, the index has to be loaded
multiplied by two, and added to the start of the array. In the 'pointer'
version all that has to happen is to increment the pointer by two. A
small saving.

If you are not doing anything else accessing the registers, you could
pre-setup the addressing register, do the 'write' by direct access, and
just increment the register by two.

So, using the 'POSTINC' register, something like:
Code:

#word FSR0=getenv("SFR:FSR0L")
#word INDF0=0xFEF //INDF0
#byte PREINC0=0xFEC //PREINC0
#byte POSTINC0=0xFEE //POSTINC0

      //Now fastest approach using postinc0
      FSR0=demo;
      //Load FSR with the address
     
      for (ctr=0;ctr<256;ctr++)
      {
         temp=read_adc();
         POSTINC0=make8(temp,0); //LSB
         POSTINC0=make8(temp,1); //MSB     
      }

//which generates:
....................       //Load indf with the address
....................       for (ctr=0;ctr<256;ctr++) 
00EE:  CLRF   ctr+1
00F0:  CLRF   ctr
00F2:  MOVF   ctr+1,W
00F4:  SUBLW  00
00F6:  BTFSS  STATUS.C
00F8:  GOTO   0120
....................       {
....................          temp=read_adc();
00FC:  BSF    ADCON0.GO
00FE:  NOP   
0100:  BTFSC  ADCON0.GO
0102:  GOTO   0100
0106:  MOVFF  ADRESL,temp
010A:  MOVFF  ADRESH,temp+1
....................          POSTINC0=make8(temp,0); //LSB
010E:  MOVFF  temp,POSTINC0
....................          POSTINC0=make8(temp,1); //MSB       
0112:  MOVFF  temp+1,POSTINC0
0116:  INCF   x06,F
0118:  BTFSC  STATUS.Z
011A:  INCF   ctr+1,F
011C:  GOTO   00F2

About seven instructions faster (if I have got it right!...).

Key here is using the POSTINC register which allows a single byte
to be transferred to where FSR0 'points', and then increments the FSR.
The two bytes have to be transferred separately (hence 'temp'), but
this means that the two bytes can actually be transferred in just a couple
of instructions.
This is done reading data from the standard PIC adc, rather than your
source, but shows how different the approaches can be.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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