#include <Wire.h>
#include <Encoder.h>
#define SSD1306_ADDRESS 0x3C //indirizzo di default del display
#define SCREEN_WIDTH 128 // Larghezza dello schermo in pixel
#define SCREEN_HEIGHT 64 // Altezza dello schermo in pixel
#define CHANNEL_HEIGHT 8 // Altezza di ciascun canale nel display
#define CHANNEL_PIXELS 12 // Numero di pixel per ciascun canale
#define PIXEL_SIZE 8 // Dimensione di ciascun pixel nel display
Encoder myEncoder(2, 3);
int encoderValue = 0;
int encoderValuePrev = 0;
float zoomFactor = 1.0; // Fattore di zoom iniziale
int currentSampleIndex = 0; // Indice del campione corrente
struct Campione {
int stato;
long timestamp;
};
Campione campioni[100]; // Massimo 100 campioni
void setup() {
Serial.begin(9600); // Inizializzo terminale che legge a 9600 bit/s
Wire.begin(); // Stabilizzo la comunicazione con il microcontrollore protocollo I2C
initSSD1306();
leggiCampioni();
}
void loop() {
encoderValue = myEncoder.read();
// Verifica se l'encoder è stato ruotato
if (encoderValue != encoderValuePrev) {
// Aggiorna il fattore di zoom in base alla rotazione dell'encoder
zoomFactor += (encoderValue - encoderValuePrev) * 0.1;
// Visualizza il segnale con il campione corrente e il fattore di zoom
simulazioneSegnale(campioni[currentSampleIndex].stato, zoomFactor);
// Aggiorna l'encoderValuePrev
encoderValuePrev = encoderValue;
}
}
void initSSD1306() {
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x00);
Wire.write(0xAF); // Accendi il display (0xAE per spegnerlo)
Wire.endTransmission();
}
void writePixel(int x, int y, int color) {
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x40); // Imposta il byte di dati
Wire.write(0x00 | x); // Imposta la coordinata X
Wire.write(0x10 | (y >> 4)); // Imposta la coordinata Y (parte alta)
Wire.write(0x00 | (y & 0x0F)); // Imposta la coordinata Y (parte bassa)
Wire.write(color ? 0xFF : 0x00); // Imposta il colore del pixel
Wire.endTransmission();
}
void setTextColor(int color) {
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x00); // Comando di inizializzazione
Wire.write(color ? 0xA6 : 0xA7); // Imposta il colore del testo
Wire.endTransmission();
}
int calcolaPixelDurata(long durata_ns, float fattore_divisione) {
// Calcola il numero di pixel sulla base della durata e del fattore di divisione
float pixel_durata = (float)durata_ns / fattore_divisione;
// Arrotonda il risultato al più vicino intero
int pixel_arrotondato = int(pixel_durata + 0.5);
return pixel_arrotondato;
}
void simulazioneSegnale(int value, float zoom) {
for (int channel = 0; channel < 8; channel++) {
// Viene calcolata moltiplicando l'indice del canale per la larghezza del canale in pixel
int channelStartX = channel * CHANNEL_PIXELS;
int channelStartY = 0;
// Pulisci il display nella zona del canale
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x00);
Wire.write(0x21); // Imposta la colonna di inizio
Wire.write(channelStartX);
Wire.write(channelStartX + CHANNEL_PIXELS - 1); // Imposta la colonna di fine
Wire.write(0x22); // Imposta la pagina di inizio
Wire.write(channelStartY);
Wire.write(CHANNEL_HEIGHT - 1); // Imposta la pagina di fine
Wire.endTransmission();
// Disegna il segnale con il fattore di zoom
for (int y = 0; y < CHANNEL_HEIGHT; y++) {
int startY = y * PIXEL_SIZE;
int endY = startY + PIXEL_SIZE;
if (y % (int)(1 / zoom) == 0) { // Applica il fattore di zoom
int pixel_da_disegnare = calcolaPixelDurata(campioni[currentSampleIndex].timestamp, zoomFactor);
if (value == 1) {
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x40); // Imposta il byte di dati
Wire.write(channelStartX); // Coordinata X inizio rettangolo
Wire.write(startY); // Coordinata Y inizio rettangolo
Wire.write(CHANNEL_PIXELS); // Larghezza rettangolo
Wire.write(pixel_da_disegnare); // Altezza rettangolo
Wire.write(0xFF); // Riempimento rettangolo
Wire.endTransmission();
} else {
// Disegna una linea per il segnale non attivo
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x40); // Imposta il byte di dati
Wire.write(channelStartX); // Coordinata X inizio linea
Wire.write((startY + endY) / 2); // Coordinata Y linea
Wire.write(CHANNEL_PIXELS); // Lunghezza linea
Wire.write(0x00); // Nessun pixel disegnato
Wire.endTransmission();
}
}
}
// Aggiorna il display
Wire.beginTransmission(SSD1306_ADDRESS);
Wire.write(0x00);
Wire.write(0x21); // Imposta la colonna di inizio
Wire.write(channelStartX);
Wire.write(channelStartX + CHANNEL_PIXELS - 1); // Imposta la colonna di fine
Wire.write(0x22); // Imposta la pagina di inizio
Wire.write(channelStartY);
Wire.write(CHANNEL_HEIGHT - 1); // Imposta la pagina di fine
Wire.endTransmission();
}
}
void leggiCampioni() {
Serial.println("Inserisci i valori dei campioni nel formato: stato,timestamp");
Serial.println("Esempio: 1,2435365875");
Serial.println("Invia 'f' per terminare l'inserimento dei campioni.");
int i = 0;
bool validInput = false;
while (true) {
if (Serial.available() > 0) {
char c = Serial.read();
if (c == 'f') {
Serial.println("Inserimento terminato! Visualizzazione dei campioni attiva");
break;
} else if (c == ',') {
if (validInput) {
// Campione memorizzato solo se il valore precedente era valido
long timestamp = Serial.parseInt();
Serial.println("Campione memorizzato");
campioni[i].timestamp = timestamp;
i++;
validInput = false; // Resetta il flag per il prossimo valore
} else {
// Ignora il carattere se non è stato inserito uno stato valido prima della virgola
Serial.println("Input non valido. Inserire 1 o 0 seguiti da una virgola.");
}
} else if (c == '1' || c == '0') {
// Imposta il flag per indicare che è stato inserito uno stato valido
validInput = true;
// Leggi lo stato
// Converto il carattere numerico ASCII nella sua controparte numerica
int stato = c - '0';
campioni[i].stato = stato;
}
}
}
}
Loading
ssd1306
ssd1306