In working on a driver for TWI (I2C), I stumbled upon a method that saves 1.2k of memory. This particular snippet had an object size of 1,318 bytes when using doubles in the speed calculation, but coercing them into uint8_t by factoring 1e4, it reduced the object size to 322. Moving that function into definition file, reduced object size by another 92 bytes. As a vehement advocate of assembly, but realizing full well, there are a lot of knowledgeable people, far more than I, that have put together GCC, I'm taking it upon myself to experiment, how some things can be done to optimize space beyond the capability of the compiler.
TWI.h I really like default parameters and it gives 4 possibilities to the same function.
#ifndef TWI_H #define TWI_H #define Sys_Clk 1600 #include <avr/io.h> #include <util/twi.h> #define SCL PINC5 #define SDA PINC4 class TWI_Interface { public: TWI_Interface (void); bool Init (uint8_t Freq = 10, uint8_t Device = 0); private: uint8_t Start, End; // IO buffer indices. char Buffer [64]; // Needs to be this size for wrap-around feature. uint8_t Speed (uint8_t Freq) { return ((Sys_Clk / Freq) - 16) / 2; } }; #endif
There are going to be a lot of things I'm going to change as development progresses. First thing I can see is that defining PORTC does not need to happen for each instance, so I'll be moving it to main.
TWI.cpp
#include "TWI.h" // Default constructor TWI_Interface::TWI_Interface () { Start = End = 0; DDRC = (1 << SDA) | (1 << SCL); } bool TWI_Interface::Init (uint8_t Freq, uint8_t Device) { TWSR &= TW_STATUS_MASK; TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); TWBR = Speed(Freq); if (!Device) { // Probe for unknown device } return true; }
main.cpp
#include "TWI.h" TWI_Interface RTClock; int main () { // Set pins 13 & 12 to ouput on Arduino DDRB = (1 << PINB5) | (1 << PINB4); if ( RTClock.Init() ) { do { } while (1); } }