Guidance using Port Manipulation on ATtiny1606

As the title suggests....

I have an ATtiny1606. Its tight for programming space on this little thing, so I am trying to make the code a bit more efficient.

The worst culprit is the <Adafruit_SSD1306.h> library, but I currently don't have a fix for that.
But... I will address that later. Maybe some custom text will work with a simple text library.

But... first I am trying to reduce the amount of DigitalWrite statements (yet to be added).
I assume using port manipulation will reduce programming space?

I cannot get the basic pinmode statement to compile, so I am clearly doing something wrong.

Any assistance would be great

I just get 'DDRA' was not declared in this scope

#include <avr/io.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define crane_on PA5         // PA5   Pin 1
#define beacon_1 PA6         // PA6   Pin 2
#define beacon_2 PA7         // PA7   Pin 3
#define beacon_3 PB5         // PB5   Pin 4
#define beacon_4 PB4         // PB4   Pin 5
#define cd4051B PC0          // PC0   Pin 10
#define cd4051A PC1          // PC1   Pin 11
#define leds_1 PC2           // PC2   Pin 12
#define leds_2 PC3           // PC3   Pin 13


//-----------------------------------------------------------------------

void setup() {

  //pinMode(crane_on, INPUT);    // PA5
  //pinMode(beacon_1, OUTPUT);   // PA6
  //pinMode(beacon_2, OUTPUT);   // PA7
  //pinMode(beacon_3, OUTPUT);   // PB5
  //pinMode(beacon_4, OUTPUT);   // PB4
  //pinMode(cd4051B, OUTPUT);    // PC0
  //pinMode(cd4051A, OUTPUT);    // PC1
  //pinMode(leds_1, OUTPUT);     // PC2
  //pinMode(leds_2, OUTPUT);     // PC3

  //DDRA = 0b11000000;                       // Pinmode for the pins.  1 = Output (Reads right to left)
  //DDRB = 0b110000;
  //DDRC = 0b1110;


  DDRA |= (0 << crane_on);                   // Set as input                     
  DDRA |= (1 << beacon_1);                   // Set as outputs
  DDRA |= (1 << beacon_2);  
  DDRB |= (1 << beacon_3);  
  DDRB |= (1 << beacon_4);  
  DDRC |= (1 << cd4051B); 
  DDRC |= (1 << cd4051A); 
  DDRC |= (1 << leds_1); 
  DDRC |= (1 << leds_2); 

  PORTB |= (1 << beacon_1);             // Beacon on
  delay(200);  
  PORTB &= ~(1 << beacon_1);          // Beacon off
  
}



void loop() {

}

I have never used the attiny 1606 myself but I took a quick look at the datasheet for you and it appears it uses different commands than the typical Uno/nano chips.

For example:
It appears that instead of DDRx
it uses PORTx.DIR

There's more to it of course, You will have to study the Datasheet unless you can find someone that has done the legwork and written a tutorial.

Link to Datasheet:
https://onlinedocs.microchip.com/oxy/GUID-F0E44D22-01FD-4672-8F9F-301992D3E816-en-US-7/index.html

Declaring pins and using them works different on the modern Attinies.

Megatinycore however provides a nice wrapper for port manipulation, that saves you already a lot of flash.

I reworked your example a bit, please have a look.

#include <avr/io.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define crane_on PA5         // PA5   Pin 1
#define beacon_1 PIN_PA6         // PA6   Pin 2
#define beacon_2 PA7         // PA7   Pin 3
#define beacon_3 PB5         // PB5   Pin 4
#define beacon_4 PB4         // PB4   Pin 5
#define cd4051B PC0          // PC0   Pin 10
#define cd4051A PC1          // PC1   Pin 11
#define leds_1 PC2           // PC2   Pin 12
#define leds_2 PC3           // PC3   Pin 13


//-----------------------------------------------------------------------

void setup() {

  //pinMode(crane_on, INPUT);    // PA5
  //pinMode(beacon_1, OUTPUT);   // PA6
  //pinMode(beacon_2, OUTPUT);   // PA7
  //pinMode(beacon_3, OUTPUT);   // PB5
  //pinMode(beacon_4, OUTPUT);   // PB4
  //pinMode(cd4051B, OUTPUT);    // PC0
  //pinMode(cd4051A, OUTPUT);    // PC1
  //pinMode(leds_1, OUTPUT);     // PC2
  //pinMode(leds_2, OUTPUT);     // PC3

  //DDRA = 0b11000000;                       // Pinmode for the pins.  1 = Output (Reads right to left)
  //DDRB = 0b110000;
  //DDRC = 0b1110;


//  DDRA |= (0 << crane_on);                   // Set as input                     
  pinModeFast (beacon_1, OUTPUT);         // Set as outputs
//  DDRA |= (1 << beacon_2);  
//  DDRB |= (1 << beacon_3);  
//  DDRB |= (1 << beacon_4);  
//  DDRC |= (1 << cd4051B); 
//  DDRC |= (1 << cd4051A); 
//  DDRC |= (1 << leds_1); 
//  DDRC |= (1 << leds_2); 

  digitalWriteFast (beacon_1, HIGH);         // Beacon on
  delay(200);  
  digitalWriteFast (beacon_1, LOW);          // Beacon off
  
}



void loop() {

}
Sketch uses 8324 bytes (50%) of program storage space. Maximum is 16384 bytes.
Global variables use 172 bytes (16%) of dynamic memory, leaving 852 bytes for local variables. Maximum is 1024 bytes.

The smallest I can get (10 bytes saved) is with pure port manipulation. You will have to select the port and the pin separately.

#include <avr/io.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define crane_on PA5         // PA5   Pin 1
#define beacon_1 PIN6_bm // PA6, PB6, etc.. generic define for the 7th pin on any port
#define beacon_2 PA7         // PA7   Pin 3
#define beacon_3 PB5         // PB5   Pin 4
#define beacon_4 PB4         // PB4   Pin 5
#define cd4051B PC0          // PC0   Pin 10
#define cd4051A PC1          // PC1   Pin 11
#define leds_1 PC2           // PC2   Pin 12
#define leds_2 PC3           // PC3   Pin 13


//-----------------------------------------------------------------------

void setup() {

  //pinMode(crane_on, INPUT);    // PA5
  //pinMode(beacon_1, OUTPUT);   // PA6
  //pinMode(beacon_2, OUTPUT);   // PA7
  //pinMode(beacon_3, OUTPUT);   // PB5
  //pinMode(beacon_4, OUTPUT);   // PB4
  //pinMode(cd4051B, OUTPUT);    // PC0
  //pinMode(cd4051A, OUTPUT);    // PC1
  //pinMode(leds_1, OUTPUT);     // PC2
  //pinMode(leds_2, OUTPUT);     // PC3

  //DDRA = 0b11000000;                       // Pinmode for the pins.  1 = Output (Reads right to left)
  //DDRB = 0b110000;
  //DDRC = 0b1110;


//  DDRA |= (0 << crane_on);                   // Set as input 
  VPORTA_DIR |= beacon_1;         // Set as outputs
//  DDRA |= (1 << beacon_2);  
//  DDRB |= (1 << beacon_3);  
//  DDRB |= (1 << beacon_4);  
//  DDRC |= (1 << cd4051B); 
//  DDRC |= (1 << cd4051A); 
//  DDRC |= (1 << leds_1); 
//  DDRC |= (1 << leds_2); 

  VPORTA_OUT |= beacon_1;         // Beacon on
  delay(200);  
  VPORTA_OUT &= ~ beacon_1;       // Beacon off
  
}



void loop() {

}
Sketch uses 8314 bytes (50%) of program storage space. Maximum is 16384 bytes.
Global variables use 172 bytes (16%) of dynamic memory, leaving 852 bytes for local variables. Maximum is 1024 bytes.

From the Adafruit_SSD1306 Memory Hog I remember that when playing with Attiny85 I used the Tiny4kOLED library instead, that saved a LOT of flash. I haven't used it with the modern attinies yet, but the examples that come with Tiny4kOLED compile for them. I'd have to rig up a test to confirm it actually works also on them.

[edit] That works just fine. The "scrolling text" example is even working on Attiny404. Try that with the Adafruit library.

Thanks all for the guidance.... I will have a look at that this evening.

The Oled library issue is for graphics.... but very small graphics. It's actually for some working radar screens etc on a model RC boat.

The circles etc are very small, so I am thinking maybe I can simply draw some custom text characters and use those with a smaller text only library.
Not sure if that will work.... but only one way to find out!

Thanks all

Don't quite understand what is going on here?

#define beacon_1 PIN6_bm // PA6, PB6, etc.. generic define for the 7th pin on any port

Do I need to rename all the pins? (instead of using PA5, PA6 etc)

I also assume to set a pin as an input, I use: VPORTA_DIR &= ~ crane_on;

Oh, and how do you read a pin state?