Loading...
  Show Posts
Pages: 1 [2] 3 4 ... 78
16  Development / Other Software Development / String lib alternative / Print class targeting memory. on: May 15, 2013, 12:02:17 pm
G'day fellow Arduino people.

I have recently put together a class which inherits the Arduino core 'Print' class, it implements a memory target which provides all the standard print functions.

I got encouraged by its possibilities and decided to flesh it out for sharing. Now its a nice alternative to 'Strings' as it allows easy concatenation of data. without a malloc/free pair for every little operation. Also it can replace basic usage of sprintf.

When using libraries such as Serial, it has little overhead as the print functionality may already be used and included.

All this said, I have not really tested it heavily, and probably needs tweaks for certain scenarios.
Any ideas are welcome also.

Here is a list of functionality.
Quote
 
  • template< typename T > GString( const T *u_DataPtr );
        Constructor: pass in a valid pointer to any memory.
      
      
  • operator char*( void );
        Conversion operator ( GString to char* ), also allows accessing string elements directly using '[]' operators.
      
      
  • template< typename T > String &operator +=( const T &t );
        Allows use of the '+=' operator on anything the Print class accepts.

      
  • void clear( void );            
        Resets the string to empty.
       
      
  • void clear( bool b_Empty );
        Clears any previous data if requested. then resets.
      
      
  • template< typename T > GString &concat( const T &t );
        Provides chainable print methods.
        
      
  • template< typename T > GString &concat( const T &t, const int i );
        Provides chanable print methods utilising the second parameter.
        
      
  • size_t count( void ) const;        
        Returns the number of characters printed into the string.
        
      
  • void end( void );            
        Adds a terminating null. Buffer will still increase after ending a string.
      
      
  • size_t find( const char &c_Character );  
        Find a character within the string. Its index is returned or -1.
      
      
  • void repeat( const char &c_Character, unsigned char u_Count );
        Prints c_Character into the string repeating u_Count times.
              
      
  • void toLower( void );          
        Converts the string into its lower case equivalent.
       
      
  • void toUpper( void );          
        Converts the string into its upper case equivalent.

      
  • void translate( const char &c_StartLow, const char &c_StartHigh, const char &c_EndLow );
        Converts a range of characters to a different part of the ascii table.
The library code is at the bottom, below is its usage.

Note: all examples produce output resembling the following:
Quote
This is a float test: 123.456
Analog pin 0 value: 439

Code:
//Buffer to store data.
char TestArr[ 128 ];

//Create string, passing in buffer pointer.
GString g_Test( TestArr );

//Use like Serial
g_Test.print( "This is a float test: " );
g_Test.println( 123.456, 3 );
g_Test.print( "Analog pin 0 value: " );
g_Test.print( analogRead( A0 ), DEC );  

The library also supports += operators:
Code:
GString g_Test( TestArr );

g_Test += "This is a float test: ";
g_Test += 123.456f;
g_Test += "\r\nAnalog pin 0 value: ";
g_Test += analogRead( A0 );

I have also added a function 'concat' for chained printing ( notice anonymous GString rather than variable ):
Code:
GString( TestArr ).concat( "This is a float test: " ).concat( 123.456, 3 ).concat( "\r\nAnalog pin 0 value: " ).concat( analogRead( A0 ), DEC );

And the GString class can be printed itself.
Code:
Serial.print( g_Test );

EDIT:
As the print functionality does not deal with null's, you have to take care when using the original pointer.
Either clear the pointer initially before use, or call end() as the last call to the GString before using the pointer.
The built in conversions are safe, a null is added, but will be overwritten if more print operations take place.
Update message.

The library:
Due to message length limits, the code is now an attachment to this post, an external link will be available soon.

Enjoy smiley

EDIT: new code update.
17  Using Arduino / Programming Questions / Re: string print methods on: May 15, 2013, 10:30:42 am
So, what if I want to do essentially the same thing but target a memory buffer, instead of a hardware device.

Seemed like a nice idea, especially if sprintf is costly. So here is my gift to you.

This is my proposal:
Code:
class MemPrinter : public Print{
public:
template< typename T >
explicit MemPrinter( const T *u_DataPtr ) : Data( ( uint8_t* ) u_DataPtr )
{ return; }
protected:

size_t write(const uint8_t *buffer, size_t size)
{
const size_t s_Return = size;
while( size-- ) *this->Data++ =  *buffer++;
return s_Return;
}

size_t write(uint8_t u_Data )
{
*this->Data++ = u_Data;
return 0x01;
}

private:

uint8_t *Data;
};

It contains all the print/ln functionality of the serial library ( mostly untested ).
Heres how it works:

Code:
//Create a buffer
char buffer[ 16 ];

//Recommend clearing buffers located on the stack ( may be filled with rubbish data )
memset( buffer, 0x00, 16 ); //Not required for MemPrinter use.

//Class in action.
MemPrinter( buffer ).print( 123.45678f );

//Print result to see
//Serial.print( buffer );

MemPrinter( buffer ).print( 123.45678f, 5 );
//Serial.print( buffer );

18  Using Arduino / Programming Questions / Re: Issues with Pass Array of Structures to Library by Reference on: May 15, 2013, 07:43:03 am
A similar discussion appears in his Beginning C Programming for Arduino, but it has two chapters just on using pointers. Unfortunately, this is a ripoff of Dr. Purdum's book, since the entire book is online for free but I do think it will help you understand pointers.

I'm confused, didn't you write "Beginning C Programming for Arduino"?

Note how I left out the size of the array in its definition...

This is always a good idea because compilers are good at counting elements in initializer lists and, if you decide to add more elements later on, you just add the element, recompile, and you're done. You don't have to remember to adjust the element count.

Remember the opposite too, by specifying a size, you can create an array larger than the list, allowing you to only initialise the elements needing a default value, which in turn generates less code in the initialisation vector.
19  Development / Suggestions for the Arduino Project / Re: Is there a project to improve/replace the official examples? on: May 15, 2013, 07:14:53 am
I agree, the Arduino folks should let a few of us tinker with the reference/example pages. The bloated bottomless pit of a playground is not the best place for reference material ( that you want people to find ), having  access to the official areas would be nice.

Like you say, many threads and headaches can be avoided with up to date / accurate information.
20  Using Arduino / Programming Questions / Re: Help with basic bit shifting on: May 14, 2013, 07:39:34 pm
Maybe something like this: ( taken the bits are 0 - 7 not 1 - 8 )

Code:
PORTB = ( ( PORTD >> 2 ) & 0b00110000 ) | ( PORTB & 0b11001111 );

@Magician, would your version still work if PORTB has 5 or 4 set and PORTD doesn't have 6 or 7 set?
21  Using Arduino / Programming Questions / Re: Passing arrays to functions on: May 14, 2013, 06:53:36 pm
You can use templates. Similar to what I poseted in liudr's thread.

Code:
template< typename T, unsigned N >
  void changeArray( T (&ary)[ N ] ){

    for( int i = 0 ; i < N ; ary[ i++ ] = 0 );
  }
22  Using Arduino / Programming Questions / Re: Problem with Arduino auto-generated function declarations on: May 14, 2013, 06:44:47 pm
Thanks. I'll do that or rearrange the order of function definitions to not need a declaration.

I would recommend putting the declaration in yourself, rather than moving the definitions around. Eventually you will get a combination that doesn't see one function, and can't be moved due to its own dependencies.

On a side note, below is how I pass most fixed sized arrays, it is functionally equivalent to your version except the compiler provides the array size rather than you having to hard code in values/defines.

Code:
template< unsigned N >
  void bad_fun( char (&arr)[ N ] )
    {
      Serial.print( "Array Size: " );
      Serial.println( N, DEC );
      return;
    }

//And you call it exactly the same:
bad_fun(char_arr);

Evidently somebody thinks so, or we wouldn't have been lumbered with it. Personally, I think it's a mistake. Done well, it would have been a bad idea because it means that C++ coding experience doesn't transfer to Arduino and vice versa. However, it wasn't done well. I'm looking forward to the day that the Arduino IDE provides an option to turn this nonsense off.

I agree, they should stick with the basic C++ principles and have people declare/include as necessary. The IDE doesn't apply its changes to any other sketch files, which gives me the impression that whoever designed the auto-gen feature assumed we would all mostly use single file sketch's. And even worse assuming people using multi file sketches won't be able to write the 'sketch' file properly.

I remember reading a couple of years ago how Arduino is designed to feel more like a simple scripting language for non-programmers and not once was C++ mentioned. It was only after a bit of investigation I found out I was able to use straight C++. ( FAQ and mission statements updated now. )

I think the whole notion of trying to dumb down C++ is flawed, and too much mention is put on C, everything is 100% C++ unless you explicitly use a *.c file.
23  Using Arduino / Programming Questions / Re: Problem with Arduino auto-generated function declarations on: May 14, 2013, 05:16:54 pm
Placing the declaration at the top works fine: 'void bad_fun(char arr[bigerr+1]);'
I think the team already is well aware of this bug, it affects function prototypes with references (&) and square brackets.
Using structs/classes as arguments also fails due to the prototype being placed above the struct.
24  Using Arduino / Programming Questions / Re: Problem Serial.available() = 0 on: May 14, 2013, 12:41:46 am
You need to send data to it for any other result. Serial.available() only returns the number of bytes in the receive buffer, not weather the serial functionality is available.
25  Using Arduino / Programming Questions / Re: [HELP] Read hex value from array problem on: May 13, 2013, 12:46:40 am
There are functions provided in pgmspace.h which allow you to read different sizes of data.

Code:

uint32_t ReadData = pgm_read_dword(&hello_01_data[ index ] );

http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
26  Using Arduino / Programming Questions / Re: [Problems] Passing multiple multidimensional arrays as parameter on: May 11, 2013, 05:45:53 am
your link seems dead. are the two variables still declared int:
Code:
int greenScreen[8][8];
int redScreen[8][8];

or are they declared as char arrays?
Code:
char greenScreen[8][8];
char redScreen[8][8];
27  Using Arduino / Programming Questions / Re: Am i over thinking things ? on: May 11, 2013, 02:52:36 am
The wireless uses SPI, so as long as you don't intend to run it off the MCP23008, it should be fine.
Connecting the LED's is up to you, should be enough free pins to use a transistor setup, or that 2003 chip will probably do too.

If your app runs too slow, there are many things you can learn to improve the code.
28  Using Arduino / Programming Questions / Re: code differences on: May 11, 2013, 12:11:43 am
Example 2 uses hard coded values, maybe a test case of what you'd expect of the first code modified for 3 servos.
By itself it is useless. Whereas example 1 allows a function to be called with different values.

Neither code does really anything apart from write text to the serial output.

What is it you want to achieve,
move servos?
print output to serial?
something else?
29  Using Arduino / Programming Questions / Re: Need help with complex #define statement on: May 10, 2013, 10:23:17 pm
I would reccomend using fatlib16's class: http://arduino.cc/forum/index.php/topic,150325.msg1128634.html#msg1128634

This should combine the two though.
Code:
#define fWrite( _pin_, _state_ ) ( ( _pin_ < 16 ) ? fWriteA( _pin_, _state_ ) : fWriteB( _pin_, _state_ ) )

It is using the C/C++ pre-processor syntax. Search macros and defines.
30  Using Arduino / Programming Questions / Re: How to make global variables accessible to libraries/classes? on: May 10, 2013, 08:45:02 am
You can use this method, it highlights multiple classes that use each other and globally accessible variables:

Globals.h
Code:
#ifndef HEADER_GLOBALS
  #define HEADER_GLOBALS
  extern char grid[ 8 ][ 8 ];
#endif

A.h
Code:
#ifndef HEADER_A
  #define HEADER_A

  #include "Globals.h"
  #include "B.h"

  class A{
    public:
      A();
    protected:
      friend class B;
  };
#endif

A.cpp
Code:
#include "A.h"

A::A(){
  return;
}

B.h
Code:
#ifndef HEADER_B
  #define HEADER_B

  #include "Globals.h"

  class B{
    public:
      B();
  };
#endif

B.cpp
Code:
#include "B.h"

B::B(){
  return;
}

Sketch:
Code:
#include "A.h"

char grid[ 8 ][ 8 ];

void setup(){}
void loop(){}

The sketch needs only include "A.h" due to A.h including B.h and Globals.h.
Pages: 1 [2] 3 4 ... 78