Bit Manipulation help

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings,

I am trying to use as little memory as possible,
using Atmel Sudio 6 on a ATMega328p

I want to break apart a BYTE for control.
and for Error detection.

Example 1 :
LEFT | RIGHT
Motor byte x x x x | x x x x
| | | Dir | | | Dir
3bit Speed 3bit Speed

I don't need 255 Levels of speed control 0-7 will be fine.
I would like to code as
Motor.LSpeed = 0; Motor.LDir = 0 ...

Example 2 :
Control byte x x x x x x x x
| | | | | | 2bit mode sel
| | | | sensor motor control
| | | Blue LED
| | Red LED
| spare
Error present
Control.Mode=0; // 0-3
Control.Sensor=0; // 0-3
Control.Blue = 0; // blue LED on or off
Control.Red = 0; // Red LED on or off
Control.Error = 0; // Bit high when ERROR

Or something like that ..
I have seen setting up Struct definitions... but can't seem to get it to work ...

Any suggestions will be greatly appreciated ...

Thank you

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have seen setting up Struct definitions... but can't seem to get it to work ...

So, what have you tried so far? What parts did "not work"?

Quote:

I am trying to use as little memory as possible,

Tell the purpose of this quest. Just to see how small you can get an app? If your app now uses 25% of SRAM and 25% of flash and 25% of EEPROM, do you get a prize for reducing those figures by a few percent?

Are you referring to flash/code space? Or SRAM/data space? What about speed?

Using a struct may well be the most straightforward, as in the example snippets you showed. It may or may not end up with the least amount of code space used; it may or may not be the fastest.

The obvious answer for the speed byte is to have separate variables for Left and Right side speeds.

struct control_byte
{
unsigned int  Mode:2;
unsigned int  Sensor:2;
unsigned int  Blue:1;
unsigned int  Red:1;
unsigned int  Spare:1;
unsigned int  Error:1;
};
typedef struct control_byte ControlB;

ControlB Control;
...
Control.Mode=0; // 0-3
Control.Sensor=0; // 0-3
Control.Blue = 0; // blue LED on or off
Control.Red = 0; // Red LED on or off
Control.Error = 0; // Bit high when ERROR

untested

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As a general rule, less data memory (by packing multiple values into single bytes or words) equates to more program memory. You might save 5 bytes of data memory and grow your program by 30 bytes of program memory in your scheme. The packed-data code will also run slower. That's all neither good nor bad, just something you need to be aware of.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you both,

The issue was all me,
This is not tested .. but it compiles

uint8_t DRIVE;
	struct{
		uint8_t RPWM : 3;	// Right motor speed 3 Bit  0-7			Bit 0-2
		uint8_t RDIR : 1;	// Right motor Direction 1= back 0=fwd	Bit 3
		uint8_t LPWM : 3;	// Left  Motor Speed 3 Bit 0-7			Bit 4-6
		uint8_t LDIR : 1;	// Left  Motor Direction 1=back 0=fwd		Bit 7
		}drive;
	uint8_t CONTROL;
	struct {
		uint8_t MODE : 2;	// Mode:: 0,0 sleep: 0,1 normal:1,0 caution : 1,1 Hazard		Bit0-1
		uint8_t SENSOR : 2;	// Sensor motor  0,0 Stop : 0,1 OUT : 1,0 IN : 1,1 STOP		BIT2-3
		uint8_t LASER : 1;	// Laser on											BIT 4
		uint8_t EYES : 1;	// Eyes on											BIT 5
		uint8_t SPARE :	1;	// spare												BIT 6
		uint8_t ERROR :	1;	// Error Accured										BIT 7
		} control;

The Idea was to have an easy way to look at or export (via Serial) the status of the two for quick debugging..
and I will be in a ATMega328 with more Flash code space than Ram space....

But I did not realize it would run slower, How can that be with it only using two byte sized "variables" .
Would it be better to create a "register" and use pointers to specific bits? .... im not sure how to.

Thanks again for your help.
Michael

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My daughter and I are building a K-9 Robot from Dr Who,

The concept is ATMEGA328 core , ATTiny85(I2c Slaved) for control timing of two servos for the Ears and a LED for the 'laser' ..
( I did this due to timing.... I wanted the ears to move inward and outward 5 times every X minutes.. (5 minutes in normal mode, 2 minutes in caution mode, 30 sec's in hazard mode.) off loaded from the main controller)

I am trying to learn more C++ as I am shifting from the Arduino IDE to Atmel using an AVRISP. More options and MUCH smaller code.... all Micro's will be running at 8Mhz.

Unfortunately I still am bouncing a bit between Arduino IDE and Atmel Studio 6. having issues with TWI on USI with the ATTiny85.

Any suggestions is always welcomed.

Michael

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But I did not realize it would run slower, How can that be with it only using two byte sized "variables" .

What is "slower", and compared to what? You didn't answer my first questioning:

Quote:

Tell the purpose of this quest. Just to see how small you can get an app? If your app now uses 25% of SRAM and 25% of flash and 25% of EEPROM, do you get a prize for reducing those figures by a few percent?

Are you referring to flash/code space? Or SRAM/data space? What about speed?


Driving a few hobby servos and a few I/O is no big deal. If it takes you 400us to close the loop, vs. 234us with a totally optimized for speed ASM program -- do you get a prize, if you have 10ms to complete the tasks?

As mentioned, if you have ample SRAM space then use whole bytes for variables and flags.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess the only reason is just for ease of porting out status to an MCP23018 for purposes of debugging. And also for learning and practicing bit manipulation .

Switching from Arduino IDE to programming with Atmel Studio any trying to learn C++ has me trying new things.

"slower" was referring to kk6gm's statement on using more code space than SRam space.

Thanks again.
Michael

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Packed data is slower because accessing it involves masking and usually shifting, as well as the memory accesses themselves.

Compare e.g.

temp_val = Stored_val;  // one val stored in one variable

to

temp_val = Packed_vals;  // fetch packed data
temp_val &= 0xE0;  // desired data is upper 3 bits
temp_val >>= 5;     // move bits to make a proper numeric val

It's even a little worse in the case of writing packed data. All those extra operations take time as well as code memory. They also make the code harder to understand. Whether that's a good tradeoff or not is entirely up to you and your team to decide.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
They also make the code harder to understand.
Only if you are doing it manually. Doing it as a bit field it is just as easy to understand.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
They also make the code harder to understand.
Only if you are doing it manually. Doing it as a bit field it is just as easy to understand.

Yep. Whenever I leave off a qualifier I usually get bitten!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you kk6gm I honestly did not think about that ...

as I am new to this ... the learning curve it pretty steep. but I will keep plugging away ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
uint8_t DRIVE;
   struct{
      uint8_t RPWM : 3;   // Right motor speed 3 Bit  0-7         Bit 0-2
      uint8_t RDIR : 1;   // Right motor Direction 1= back 0=fwd   Bit 3
      uint8_t LPWM : 3;   // Left  Motor Speed 3 Bit 0-7         Bit 4-6
      uint8_t LDIR : 1;   // Left  Motor Direction 1=back 0=fwd      Bit 7
      }drive;
   uint8_t CONTROL;
   struct {
      uint8_t MODE : 2;   // Mode:: 0,0 sleep: 0,1 normal:1,0 caution : 1,1 Hazard      Bit0-1
      uint8_t SENSOR : 2;   // Sensor motor  0,0 Stop : 0,1 OUT : 1,0 IN : 1,1 STOP      BIT2-3
      uint8_t LASER : 1;   // Laser on                                 BIT 4
      uint8_t EYES : 1;   // Eyes on                                 BIT 5
      uint8_t SPARE :   1;   // spare                                    BIT 6
      uint8_t ERROR :   1;   // Error Accured                              BIT 7
      } control;

Tell me about DRIVE versus drive and CONTROL versus control in this. I can't help thinking you were trying to create a union{} but that you are getting the syntax wrong. Did you perhaps mean something like:

typedef union {
   uint8_t DRIVE;
   struct{
      uint8_t RPWM : 3;   // Right motor speed 3 Bit  0-7         Bit 0-2
      uint8_t RDIR : 1;   // Right motor Direction 1= back 0=fwd   Bit 3
      uint8_t LPWM : 3;   // Left  Motor Speed 3 Bit 0-7         Bit 4-6
      uint8_t LDIR : 1;   // Left  Motor Direction 1=back 0=fwd      Bit 7
      }drive;
} drv_u;

drv_u combined;

combined.drive.RPWM = 5;
combined.drive.RDIR = 1;

uart_send_status(combined.DRIVE);

where the uart routine sends the complete, packed uint8_t?