/**************************************************************************
Timer full info
per far funzionare il semaforo occorre tener premuto il pulsante
• Timer 0 - 8 bit e gestisce delay(), millis(), micros(), le porte PWM 5 e 6
• Timer 1 – 16 bit (65536) e gestisce le librerie servo e le porte PWM 9 e 10
• Timer 2 – 8 bit e gestisce le funzioni tone(), le porte PWM 3 e 11,
il pin 11 è usato anche per il MOSI dell’interfaccia SPI
Manually setting up a timer will stop analogWrite() from working.
Trafic light is enabled if the button stay pushed
https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
FreeMono12pt7b.h FreeSansBoldOblique12pt7b.h FreeMono18pt7b.h FreeSansBoldOblique18pt7b.h
FreeMono24pt7b.h FreeSansBoldOblique24pt7b.h FreeMono9pt7b.h FreeSansBoldOblique9pt7b.h
FreeMonoBold12pt7b.h FreeSansOblique12pt7b.h FreeMonoBold18pt7b.h FreeSansOblique18pt7b.h
FreeMonoBold24pt7b.h FreeSansOblique24pt7b.h FreeMonoBold9pt7b.h FreeSansOblique9pt7b.h
FreeMonoBoldOblique12pt7b.h FreeSerif12pt7b.h FreeMonoBoldOblique18pt7b.h FreeSerif18pt7b.h
FreeMonoBoldOblique24pt7b.h FreeSerif24pt7b.h FreeMonoBoldOblique9pt7b.h FreeSerif9pt7b.h
FreeMonoOblique12pt7b.h FreeSerifBold12pt7b.h FreeMonoOblique18pt7b.h FreeSerifBold18pt7b.h
FreeMonoOblique24pt7b.h FreeSerifBold24pt7b.h FreeMonoOblique9pt7b.h FreeSerifBold9pt7b.h
FreeSans12pt7b.h FreeSerifBoldItalic12pt7b.h FreeSans18pt7b.h FreeSerifBoldItalic18pt7b.h
FreeSans24pt7b.h FreeSerifBoldItalic24pt7b.h FreeSans9pt7b.h FreeSerifBoldItalic9pt7b.h
FreeSansBold12pt7b.h FreeSerifItalic12pt7b.h FreeSansBold18pt7b.h FreeSerifItalic18pt7b.h
FreeSansBold24pt7b.h FreeSerifItalic24pt7b.h FreeSansBold9pt7b.h FreeSerifItalic9pt7b.h
**************************************************************************/
//#include <SPI.h> // protocollo SPI alternativo al i2c
#include <Wire.h> // protocollo i2c per settare ad esempio la velocità
#include <Adafruit_GFX.h> // font
#include <Adafruit_SSD1306.h>
#include <stdio.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int start_h=15, start_m=04, clk=53;
char outstr[30];
#define led1 12 // led 1
#define led2 11 // led 2
#define led3 10
#define button 3 // pulsante sulla porta 3
//volatile bool buttonState;
volatile bool state=false;
volatile long counter=0L,start=0L,stop=0L;
void rising_count() {
// interrupt
stop=millis();
attachInterrupt(digitalPinToInterrupt(button),count,FALLING);
TIMSK1 &=0b11111000; // disabilita i tre interrupt
}
void count() {
// interrupt
start=millis();
attachInterrupt(digitalPinToInterrupt(button),rising_count,RISING);
counter++;
/*
TIMSK1 |= (1 << OCIE1B); // enable Timer1 low value interrupt TIMSK1 |= B00000100;
TIMSK1 |= (1 << OCIE1A); // enable Timer1 high value interrupt TIMSK1 |= B00000010;
TIMSK1 |= (1 << TOIE1); // enable Timer1 overflow interrupt TIMSK1 |= B00000001;
TCNT1=N; il restar value deve essere messo sempre nel
OVF interrupt function
*/
TIMSK1 |=0b00000111; // abilita i tre interrupt
}
void setup() {
Serial.begin(9600);
//Wire.begin();
//Wire.setClock(400000L); // velocità dell' i2c
// Display setup
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay(); // cancella il logo iniziale di Adafruit
cli(); // disable global interrupts = noInterrupts()
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(9,OUTPUT);
pinMode(button,INPUT_PULLUP);
// START
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
delay(1600);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
// timer setup
// TCCR mode setup
// reset
TCCR1A = 0;
TCCR1B = 0;
/* Mode TCCR1A
TCCR1A |= (1 << WGM11) | (1 << WGM10);
pwm set
TCCR1A |= (1 << COM1B1)| (1 << COM1B0) ; //PIN10
TCCR1A |= (1 << COM1A1)| (1 << COM1A0) ; //PIN9
*/
TCCR1A |= (1 << COM1A0); //| (1 << COM1A0) ; //PIN9
/* Mode TCCR1B
CTC Consente di generare solo forme d'onda quadre (duty cycle 50%)
TCCR1B |= (1 << WGM13); // | (1 << WGM12);
*/
/* prescaler set
1-8-64-256-1024
• Timer 0 CS02 CS01 CS00
• Timer 1 CS12 CS11 CS10
• Timer 2 CS22 CS21 CS20
//(1 << CS10); 1
//(1 << CS11); 8
//(1 << CS11)|(1 << CS10); 64
//(1 << CS12); 256
//(1 << CS12)|(1 << CS10); 1024 // Solo Timer1
*/
TCCR1B |= (1 << CS12)|(1 << CS10); //1024 solo Timer1
/* compare level set
compare match register = [ 16,000,000Hz/ (prescaler * desired interrupt frequency) ] - 1
Timer1 max 65535 else 255
periodo massimo 4 secondi e 190 centesimi
*/
OCR1A = 55000;
OCR1B = 50000;
// interrupt set
/* enable is in pushbutton interrupt function "Push to RUN"
TIMSK1 |= (1 << OCIE1B); // enable Timer1 low value interrupt TIMSK1 |= B00000100;
TIMSK1 |= (1 << OCIE1A); // enable Timer1 high value interrupt TIMSK1 |= B00000010;
TIMSK1 |= (1 << TOIE1); // enable Timer1 overflow interrupt TIMSK1 |= B00000001;
TCNT1=N; // Timer1 restar value da inserire in OVF interrupt function
*/
/* input capture 1 (ICP1) interrupt : solo con Timer1 PIN8
occorre settare
prescaler TCCR1B |=0b00000xxx;
noise cancel TCCR1B |=0b10000000;
rising / falling TCCR1B |=0b01000000;
abilitazione interrupt ISR(TIMERx_CAPT_vect)
TIMSK1 |= 0b00100000;
TCNT1=0;
Viene salvato il valore corrente del Timer in ICR1 ogni volta che un evento
esterno (rising o falling) interessa il PIN8 di Arduino1.
il Timer lancia la routine di interrupt ISR(TIMERx_CAPT_vect) durante la quale
va letto il valore di ICR1
https://www.youtube.com/watch?v=N5VQZTDNcj0
Allegato II : Input Capture Mode
*/
sei(); // enable global interrupts = interrupts()
attachInterrupt(digitalPinToInterrupt(button),count,FALLING);
TCNT1=0; // Timer1 restar value va reinpostato con OVF
display.setTextSize(2); // 2:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(36, 22); // top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
display.write("START");
display.display();
delay(300);
display.clearDisplay();
// READY
display.setTextSize(1); // Normal 1:1 pixel scale
display.setCursor(6,0);
display.print("COUNTER");
display.setCursor(80, 24);
display.setTextColor(SSD1306_WHITE);
display.print("00000");
reset_watch();
}
ISR(TIMER1_COMPB_vect) {
state =2;
//digitalWrite(led1,LOW);
//digitalWrite(led2,HIGH);
//digitalWrite(led3,LOW);
PORTB |= B00001000;
PORTB &= B11101011;
}
ISR(TIMER1_COMPA_vect) {
state =3;
//digitalWrite(led1,LOW);
//digitalWrite(led2,LOW);
//digitalWrite(led3,HIGH);
PORTB |= B00000100;
PORTB &= B11100111;
}
ISR(TIMER1_OVF_vect) {
state =1;
//digitalWrite(led1,HIGH);
//digitalWrite(led2,LOW);
//digitalWrite(led3,LOW);
PORTB |= B00010000;
PORTB &= B11110011;
/* assegnando a TCNT1 un valore maggiore di zero
DOPO IL RESET di overflow NON RIPARTE DA ZERO
ma dal valore assegnato a TCNT1 */
TCNT1=40000;
}
void reset_watch (void){
// simula inizializzazione del RTC
start_h=17;
start_m=59;
clk=53;
}
void clock(void)
{
// cancella vecchio orario
display.setCursor(80, 0);
display.setTextColor(SSD1306_BLACK);
sprintf(outstr,"%02d:%02d:%02d",start_h,start_m,clk);
display.print(outstr);
// simula RTC
if(clk==59) {
if(start_m==59){
if(start_h==23) start_h=0;
else start_h++;
start_m=-1;
}
start_m++;
clk=-1;
}
clk++;
// stampa orario aggiornato
display.setCursor(80, 0);
display.setTextColor(SSD1306_WHITE);
sprintf(outstr,"%02d:%02d:%02d",start_h,start_m,clk);
display.print(outstr);
display.display();
}
void loop() {
/*
static long now,last,old_counter=0;
static int k=0;
if((stop-start)>1200)
{ //RESET Counter
stop=0L;
start=0L;
counter=0L;
}
if(counter!=old_counter)
{ // print counter
display.setCursor(80, 24);
display.setTextColor(SSD1306_BLACK);
sprintf(outstr,"%05d",old_counter);
display.print(outstr);
display.setCursor(80, 24);
display.setTextColor(SSD1306_WHITE);
sprintf(outstr,"%05d",counter);
display.print(outstr);
old_counter=counter;
display.display();
}
// aggiorna orario sul display ogni 1000ms
// meglio farlo con un timer
now=millis();
if( (now-last) > 1000L)
{ clock();
last=now;
k++;
// funzione di debug
if(k==900)
{ // ogni 15 minuti resetta l'orologio
k=0;
reset_watch();
} } */}