The biggest challenges: were getting used to the limitation 32kb code on 2k sram , having only a basic ide and not having a an stl
well, while the first challenge still exist, the ide and stl have been solved menawhile.
There are a lot of traditional programming tools/libraries that you will have to learn to replace with a totally different approach. For instance Cosa does not use malloc/free or new/delete. This is a very active design decision. Memory usage has to be rethinked and alternative design patterns used. It is all about program transformation (actually).
Is there a way, to register for pin changes without subclassing the PinChangeInterrupt ? I mean something more basic like just registering a callback method directly ? And last but not least... Just to avoid any misunderstanding: Pin::PIN(x) returns the port input register for that given pin - right ?
The quick answer is NO but there are always work-arounds. The thing is that subclassing is the thing to do. It actually helps with the larger picture. At first it looks like a lot of extra work and classes might seem a bit too advanced for the function you want to implement but if you need an environment/state the instance is the right place to put it. Callbacks are just a poor mans solution where you might endup with a singleton (i.e. use a lot of global/static variables for the state) and it just doesn't scale very well. The Arduino HardwareSerial code is a very good example of this.
My recommendation is stick to the OOP style. It is as fast and it helps you avoid memory issues. And suddenly you will endup with member function reusage that you would never had thought of in traditional C.
hmmm... i think it would be more useful to just wrap it - so no (or almost no) changes are needed once a new u8g lib is released...
Another design decision in Cosa. There is no wrapping of other libraries. There is only clean C++/OOP design with a minimum of #define's and only for syntactical sugar and variant handling. Many Arduino libraries use a lot of #define's for constants, etc. With C++ there are so many other better ways to do this and the code become both more readable and the compiler can do a much better job.
Actually the Cosa Canvas class is maybe the most "virtual". Basically to implement a new device you need to implement a single member function; draw_pixel(). And then there are a bunch of optimizations to speed things up. But it is really simple to get something started. A fun example is the OffsetScreen Canvas. It is 1-bit depth mono-chrom. And (yes) a template class. You can allocate it on the stack, draw the image and transfer it to a device. Below is the member function that does the job. Canvas handles lines, rectangles, circles, fonts, etc.
virtual void draw_pixel(uint8_t x, uint8_t y)
if ((x > WIDTH) || (y > HEIGHT)) return;
uint8_t* bp = &m_bitmap[((y >> 3) * WIDTH) + x];
uint8_t pos = (y & 0x07);
if (get_pen_color().rgb == Canvas::BLACK)
*bp |= (1 << pos);
*bp &= ~(1 << pos);
I think it is important to remember that most of the libraries in Arduino are by students and people that simply want to share their hobby. Only a very little fraction of the libraries are written by software professionals. There is also a problem with a lot of the example code and application notes from chip vendors. Most of them are low level and difficult to reuse. Which in some sense explains some of the wrapping in Arduino.
One of the motivations to invest time and effort in Cosa is to help give examples of how some of all these libraries can be rewritten and use more of the power of C++ and OOP.