C++17 component to use SSD1306 displays using ATtiny85

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

Hi,

 

I would like to share with you my work to develop a generic component written in C++17 to use SSD1306 displays controlled by ATtiny85.

The key points about this work are:

1. High level of abstraction;

2. Code reusability;

3. High space efficiency.

 

My initial motivation was to explore how a modern C++ approach can be used to develop good programs to ATtiny85. It seems to me that the majority of the community that have the space performance as a goal is ignoring C++ because believes that the language can't perform so well as the C programming language. This is true when we are talking about an "archaic C++" that uses dynamic polymorphism and doesn't abuse of the compile-time phase that can bring run-time bugs to compile-time and can do other things like generate optimized code under the hood. 

 

Let me know what you think.

 

https://github.com/ricardocosme/...

 

--

Cosme


Cosme

Last Edited: Mon. Jan 20, 2020 - 12:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Helpful, thanks for showing this.

 

Can you explain what sed is doing, I have not used it in years and years and years.

 

https://github.com/ricardocosme/att85/blob/develop/demo/ssd1306/Makefile#L19

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

Certainly, it's true that C++17 offers a lot of fancy new features that might allow better code generation. How does that work out? Do you have any benchmarks or comparisons for space used by roughly comparable programs and libraries?

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

ron_sutherland wrote:

Can you explain what sed is doing, I have not used it in years and years and years.

 

https://github.com/ricardocosme/att85/blob/develop/demo/ssd1306/Makefile#L19

Yes, we're using the 's' command of the sed to insert the makefile that lists the dependencies of a source as a target of itself. For example, let's suppose that we have a source 'main.cpp' with the following content:

//main.cpp
#include "foo.hpp"
int main(){}

Let's suppose that 'foo.hpp' doesn't have any includes at all. So, the object file 'main.o' have two dependencies: 'main.cpp' and 'foo.hpp'. We can have a makefile(main.d) to represent this scenario:

main.o : main.cpp foo.hpp

This is important because we would like to automatically recompile 'main.o' when make is executed and one of the dependencies like 'foo.hpp' has changed. But, if 'main.d' isn't a target of itself, one natural change in the list of the dependencies, like adding a new include in 'foo.hpp', for example, the 'main.d' will not be regenerated automatically to consider the new header that was included by 'foo.hpp'. The sed here is doing this task of put the makefile with suffix .d as a target of itself. Which means that the above example will be replaced by sed to the following:

main.o main.d : main.cpp foo.hpp

The sed command can be read as:

sed 's,\(main\)\.o[ :]*,\1.o main.d : ,g' < main.d

The regexp here is:

\(main\)\.o[ :]*

We capture the string "main" that is immediately followed by the sequence ".o : ".

The replacement here is: 

\1.o main.d :

We recover the captured string, which is the sequence "main", and the matched sequence is replaced by: 

main.d main.d : 

BTW, this solution to handle dependencies is provided by the utility make. Please, take a look at: https://www.gnu.org/software/mak...
 


Cosme

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

Thank you for that, I need to get C++ working with the 5.4.0 version that I am using first, I can then compare listings with a newer version (e.g., https://www.avrfreaks.net/forum/...). I don't trust this stuff, so I like to have a reference that I have done some testing on.

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

the_real_seebs wrote:

Certainly, it's true that C++17 offers a lot of fancy new features that might allow better code generation.

IMO, this isn't about C++17. The main point here is about how you use the language. We can achieve a result as good as what we have with C++17 using the C++11/14, or why not, C++98/03. The modern C++ "began" around 2001, actually, in that year at least we had a public publication about modern practices which are very important to achieve the goals mentioned in this post. 

 

the_real_seebs wrote:

How does that work out?

You can use a lot of the effort that the compiler can offer. Through the usage of meta functions and constexpr functions the component can take important decisions at compile-time. Some examples based on this work:

1. The att85::display component uses Policies(types in the end) to decide what it need to do at the initialization of the display without taking branches in run-time. We can see this at display.hpp:157 and detail/reset.hpp:92;

2. The processing of a string in compile-time permits an assembly without a run-time loop to walk in a charset table and we put in the storage(flash memory) only the glyphs(chars) that will be used by the program, instead of the whole table;

3. It's possible to edit a char image using the bitmap in the orientation of the screen, take a look at att85/ssd1306/font/16x32/chars.hpp:19, please. There is a constrexpr function toGDDRAM to translate in compile-time this human representation to the required model.

 

the_real_seebs wrote:

Do you have any benchmarks or comparisons for space used by roughly comparable programs and libraries?

Yes. I pushed one benchmark related to the library(tinusaur-ssd1306xled) that I used before write this.

https://github.com/ricardocosme/...

 

I'm also developing the component with benchmarks between att85 and adhoc versions that only uses free functions of the detail namespace. I will push those as soon as possible.

 

Thank you for your interest.


Cosme