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

Reading 6 bits from a byte

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



Joined: 23 Jun 2011
Posts: 31
Location: UK

View user's profile Send private message

Reading 6 bits from a byte
PostPosted: Thu Jun 23, 2011 5:28 am     Reply with quote

Hi,

I'm storing some 6-bit Graphics in a Const char array (in Prog memory), but to be memory efficient I'm storing it consecutively: -

Code:
    array [0]            array [1]
7 6 5 4 3 2 1 0       7 6 5 4 3 2 1 0 .....   bit numbers in array
---------------       ---------------
1 0 0 1 0 1 0 1       0 0 1 0 1 1 0 1 .....   data in array
---------------       ---------------
5 4 3 2 1 0 5 4       3 2 1 0 5 4 3 2 .....   bit numbers for LCD



Apart from bit scanning, is there a more efficient way of extracting the data from the array in 6 bit chunks??

I've posted my code to do this below : -
Code:

for ( r = 0 ; r < sprite_height ; r++, curs_addr += 0x28 ) {
        pix_count = 0;
        bit_out = bit_offset;                           // This is offsetting the start bit of the sprite
        cursor_position ( curs_addr );
        for (;;) {
            data_read = cursor_up[x];                    // Fetching the gfx data from the ROM
            for ( bit = 7 ; bit >= 0 ; bit--, bit_out-- ) {               
                if ( bit_test ( data_read, bit ) ) bit_set ( datatosend, bit_out);
                pix_count++;
            if ( pix_count == sprite_width );
                else if ( bit_out != 0 ) continue;
                bit_out = 6;
                display_gfx ( datatosend );
                datatosend = 0;
                if (pix_count == sprite_width) break;
            }
            x++;
            if ( pix_count == sprite_width ) break;
        }
    }



I'm using PIC18F4620.

Any comments/suggestions on this code would be appreciated!

Thanks
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Jun 23, 2011 7:28 am     Reply with quote

How about a different approach. This will require less shifting especially when combined with the swap instruction.

I refer to a sample as one of the 6 bit data values.
Store four samples (A,B,C,D) in three bytes as follows:

    Sample A is stored in the lower six bits of location N
    Sample B is stored in the lower six bits of location N+1
    Sample C is stored in the lower six bits of location N+2
    Sample D lower 2 bits is stored in the upper 2 bits of N
    Sample D middle 2 bits is stored in the upper 2 bits of N+1
    Sample D upper 2 bits is stored in the upper 2 bits of N+1

_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Thu Jun 23, 2011 8:31 am     Reply with quote

Was about to post a couple of suggestions, and see Asmallri has posted half the same idea.

For an incoming 'object_number', you have:
Code:

   
    byte_address=object_number/4;
    val=object_number&3;
    byte_address+=byte_address*2;
    byte_address+=start_of_array;

    //Then byte_address is the address in the integer array you want to work
    //relative to, and val, determines what number to fetch
    switch (val) {
    case 0:
        val=*(byte_address) & 0x3F;
        break;
    //etc..


This gives very efficient calculation of whether you are dealing with value A,B,C or D, and calculation of the array starting byte from the object number (/4*3 - the first is done as a rotation, as is *2).

Cases, 1&2, are identical, with 1 or two byte offsets.

Case 3, would be the 'fiddliest', but even this, can be done quite efficiently, using standard instructions. Look at rotating the top two bits _right_ twice (CCS rotate_right function), then (as asmallri says) swapping the high and low nibble (swap), and or'ing the top two bits of this into place, and then rotating the top byte left by two.

Something like:
Code:

    int a,b,c;
    a=*(byte_address) & 0xC0;
    b=*(byte_address+1) & 0xC0;
    c=*(byte_address+2) & 0xC0;
    //This could be written using an array, but then increases the work later
    rotate_right(&a,1);
    rotate_right(&a,1);
    swap(b);
    rotate_left(&c,1);
    rotate_left(&c,1);
    a|=b;
    a|=c;


Best Wishes
Tom Jetland



Joined: 23 Jun 2011
Posts: 31
Location: UK

View user's profile Send private message

PostPosted: Fri Jun 24, 2011 2:23 am     Reply with quote

Thanks guys,

I'll try these methods out and see how they fit in with my application.

Thanks for the input and ideas :-)
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