Chris--A / PGMWrap

A concept library for easy use of PROGMEM data.
18 stars 5 forks source link

Small Feature requests #1

Open NicoHood opened 8 years ago

NicoHood commented 8 years ago

I just saw your library, didnt use it yet but had a few notes:

I also saw your EEPROM Wrap library. Both are looking very cool, I will take a look at this for sure in the future. Are you sure that there wont be any overhead? If so, why dont "they" use it in the upstream, like in the avr libs or at least inside the Arduino project?

Chris--A commented 8 years ago

YEah, I just rushed it through to get it added before the weekend, most of these are planned for tonight.

This is a read only version of the EEWrap lib for progmem, so the data cannot use assignment operators.

Gotta rush off I'll answer the other questions tonight. Thanks for the report.

Chris--A commented 8 years ago

Having size_t would be nice

I can certainly add in a size_t variant. What would you name it? I can add in a size_e & size_p for EEWrap & PGMWrap.

Why not use #pragma once?

I just use include guards to do the same thing. However the newer versions of GCC may have better optimizations for this (#pragma once) and allow faster compilation. It can't hurt to add it, would you recommend using both or just pragma directives?

Operators like += /= are missing

As mentioned above, the types provided are just like traditional PROGMEM data and is const. The EEWrap lib supports it as it allows random access.

why is this a keyword?

The PGMWrap type is the driving code for this lib (just like EEWrap), aside from the types I have pre-provided, you can go ahead and make your own types your self. For example if you do not want to access members of a struct individually, you can use normal types and make the whole object a PGMWrap type:

#include <PGMWrap.h>

struct Foo{
  int a;
  float b;
};

typedef const PGMWrap<Foo> pFoo;

pFoo foo PROGMEM = {{ //Requires 2nd lot of braces to initialize internal Foo structure.
  123,
  3.14f
}};

void setup() {
  Serial.begin(9600);

  //Load entire struct directly into a variable or function accepting a 'Foo'.
  func(foo);
}

void func(Foo f){
  Serial.println( f.a );
  Serial.println( f.b );
}

void loop() {}

I'll make this into a documented example, for both EEWrap & PGMWrap.

Does this work inside classes?

Yes, however the PROGMEM (not my lib) does have a limitation: basically as PROGMEM data must be set at compile time, you'd have to have a global or class-static to initialize it. The EEWrap does not require this as you can write to it at any time (and the IDE does not load ee init data anyway).

However there is nothing stopping you from using this to point to static data, for instance: user defined data passed into a class:

#include <PGMWrap.h>

struct Foo{

  Foo( uint8_p *in, int length ) : userStr(in), len(length) {
    Serial.begin(9600);  
  }

  void doStuff(){
    for( int i = 0 ; i < len ; ++i ){
      Serial.write( userStr[i] );
    }
  }

  uint8_p *userStr;
  int len;
};

const char userProvidedData[] PROGMEM = "A string of PROGMEM data!";

void setup() {

  Foo foo( (uint8_p*) userProvidedData, sizeof(userProvidedData) );

  foo.doStuff();
}

void loop() {}

I've still got to add in some conversions so you will not need to use a cast ((uint8_p*) userProvidedData).


There is also the benefit (once I've added the conversions) to overload functions which can accept PROGMEM data, as well as standard RAM based data.

Are you sure that there wont be any overhead?

As the objects reside in either EEPROM or PROGMEM only a pointer is emitted. The whole object will be compiled out to either read or write operations (just like my EEPROM lib already in the AVR core.) The only time the pointer will hang around in memory is when used in a non-static algorithm like the pointer in the Foo object from my second example, where it is used with a run-time only offset. But PGMWrap objects used in static code will disappear entirely leaving only the essential code (e.g. userStr[4] will become a simple pgm_read_byte( 4 ) operation).

why dont "they" use it in the upstream, like in the avr libs or at least inside the Arduino project?

Once I have the libs at a stable and well documented/tested design, I do not see why they couldn't become a staple part of the core.

NicoHood commented 8 years ago

I can certainly add in a size_t variant. What would you name it? I can add in a size_e & size_p for EEWrap & PGMWrap.

Yep. On avr it should be equal to uint16_t.

I just use include guards to do the same thing. However the newer versions of GCC may have better optimizations for this (#pragma once) and allow faster compilation. It can't hurt to add it, would you recommend using both or just pragma directives?

I read up on this and just #pragma makes more sense. However I added an identifier to see if a library is available. I also used this identifier as version identificater and do this in all of my libraries now: https://github.com/NicoHood/IRLremote/blob/dev2/src/IRLremote.h#L27-L35

As mentioned above, the types provided are just like traditional PROGMEM data and is const. The EEWrap lib supports it as it allows random access.

How dumb... sorry you are right^^

The PGMWrap type is the driving code for this lib (just like EEWrap), aside from the types I have pre-provided, you can go ahead and make your own types your self. For example if you do not want to access members of a struct individually, you can use normal types and make the whole object a PGMWrap type:

Holy! (just never use float examples on avr please. Also never comment at the right, only above (because of scrolling and the look of the code) But that sounds amazing!

Once I have the libs at a stable and well documented/tested design, I do not see why they couldn't become a staple part of the core.

Great!

Thx for the feedback :)

TiggrHH commented 8 years ago

Hello, I am a new user to GitHub, I have been looking for software with these functions for a while I am using ESP 12 E and I was struggling to get my head around PROGMEM I just thought I would let you know that I have tried this software on ESP8266 and it works as far as I have used it if you change #include <avr/pgmspace.h> to #include you do get a warning saying that it is not designed for this architecture but it compiles and seems to work

sorry if this is in the wrong place i only registered so I could let you know and maybe then other ESP users could use this wonderful tool Thanks Tiggr

forgot to say I am using Arduino IDE 1.6.8 NodeMCU v1.0 (ESP8266 12 E

I used you software to store very large ( >100k byte ) arrays for DotStar Pixel patterns T

Chris--A commented 8 years ago

I've got an ESP, so I can test it.

As far as I thought PROGMEM was simply a define to nothing in the ESP, so the lib would work, it just will keep everything in RAM,

However if @igrr has implemented the ESP version of PROGMEM and pgm_read_byte then it is quite likely that it'll work without trouble.

I'll check it out when I'm at home (just got to work), and I'll let you know.

Teddyz commented 8 years ago

Hello, I just started to love this library! Like Tiggr I would be very happy if you can make it work on ESP8266 too.

Thanks

TiggrHH commented 8 years ago

Hello I am quite new to avr, ESP and C++ (2 years on and off) line 8

include avr/pgmspace.h

prevented the IDE compiling on ESP8266 as it isnt an avr all i did was to change it to

include pgmspace.h

and it compiled fine although it did give a compatability warning

WARNING: library PGMWrap claims to run on [avr] architecture(s) and may be incompatible with your current board which runs on [esp8266] architecture(s).

i didnt know what to alter to prevent this

i crammed 72 arrays approximately 4,400 bytes each into an ESP -12E the arrays alone should have used 317,000 bytes (far in excess of the 81,920 bytes of ram available) compile output as follows:

Sketch uses 468,801 bytes (44%) of program storage space. Maximum is 1,044,464 bytes. Global variables use 45,656 bytes (55%) of dynamic memory, leaving 36,264 bytes for local variables. Maximum is 81,920 bytes.

the sketch i wrote was over 33,000 lines long due to the arrays it was to run a pair of 36 pixel high POV DotStar LED Poi displaying Python converted gif images and they worked just fine this can only mean that this library works on ESP even with the compatability warning

the Arduino IDE is 1.6.8 with all the bits and bobs for ESP

Hope this helps as this library made my task so much simpler for which i am eternally grateful

Tiggr

Teddyz commented 8 years ago

Thanks Tiggr for the update and good explanation. I did the same change and also got it to work. I can live with that warning. :) I guess that you need the a fast CPU to update all LEDs, so ESP seems as a good choice.

TiggrHH commented 8 years ago

Glad it helped This should be included in the IDE as it is so much simpler to use Yes I needed a fast MCU but my main reasons for using ESP was its massive storage and Wireless capability. When I eventually get round to it I want to have multiple RX Poi all synced up to one TX ESP attached to a small TFT with micro SD so that frames can be selected from however many images, placed in some sort of order then sent to all poi at once over UDP Got as far as UDP from one to another Just need to get my head around image parsing from SD T

Chris--A commented 8 years ago

Cheers guys for testing :)

I will look around to see if I can mark the library as suitable for the esp. As far as I know the lib manager only supports AVR, Sam, All (*)

TiggrHH commented 8 years ago

You're Welcome Chris Please could you let us know if you sort the compatability warning T

Chris--A commented 8 years ago

Yeah, I'll post any news.

Chris--A commented 8 years ago

I have found the source, and yes PGMWrap is fine to use with the ESP8266 because all the AVR defines have been re purposed for ESP8266: pgmspace.h, pgmspace.cpp