I made the serial protocol break using Timer1 on Nano ( 328P ), help please

Hello !

I used the timer 1 in the usual avr way and my serial console just stops working, commenting the timerSetup method which just sets up the timer fixes that behaviour. Could someone give me a hint please which way I could use to fix this? Timer 1 provides a pwm for 4 pins for me using its interrupt ( resulting in a rough 18khz pwn )

#include <avr/io.h>
#include <avr/interrupt.h>
#include "functionpointer.h"

int tot_overflow = 0;

uint8_t signatureFan[4] = { 'a', 'b', 'c', '?'};
uint8_t matchFan = 0;
uint8_t signatureTemp[3] = { 'd', 'e', 'f' };
uint8_t matchTemp = 0;
uint8_t temperatures[12] = { 12 };

volatile uint8_t speeds[4] = { 5, 5, 5, 5 };
int state = 1;

uint8_t extraPar;

ISR(TIMER1_OVF_vect)
{
  tot_overflow++;

  if (state == 1)
  {
    PORTC |= (1 << PC0) | (1 << PC5) | (1 << PC3);
    state = 2;
  }
  if ( state == 2) {
    if ( !(speeds[0] == 10) && tot_overflow >= speeds[0] ) {
      PORTC &= ~((1 << PC0));
    }
    if ( !(speeds[1] == 10) && tot_overflow >= speeds[1] ) {
      PORTC &= ~((1 << PC5));
    }
    if ( !(speeds[2] == 10) && tot_overflow >= speeds[2] ) {
      PORTC &= ~((1 << PC3));
    }
    if ( !(speeds[3] == 10) && tot_overflow >= speeds[3] ) {
      //PORTC &= ~((1<<PC0) | (1<<PC5));
    }
  }
  if ( tot_overflow >= 10 ) {
    state = 1;
    tot_overflow = 0;
  }
}

EMPTY_INTERRUPT (TIMER1_COMPA_vect);

//typedef void (*p_func)(int);
void matchSerialInput(unsigned int incomingByte, uint8_t * signature, uint8_t matchLength, uint8_t * match, p_func function) {
  if ( signature[*match] == incomingByte ||  signature[*match] == '?' ) {
    (*match)++;
    return;
  }
  if ( *match == matchLength ) {
    incomingByte = incomingByte - 48; // Substract ASCII encoding
    function(incomingByte);
    *match = 0;
  } else {
    *match = 0;
    if ( signature[*match] == incomingByte ) {
      (*match)++;
    }
  }
}

uint8_t getFromBuffer() {
  return extraPar;
}


// command example: abc1i
// inc between 1-4
// Speed between a-k
// a = 0
// k = 10
// to set, value n + 97 in ascii
void setFan( uint8_t fanSpeed ) {
  //Serial.println("Matched fan");
  uint8_t inc = getFromBuffer();
  inc = inc - 48;
  fanSpeed = fanSpeed + 48;
  fanSpeed = fanSpeed - 97;
  if ( inc >= 1 && inc <= 4 ) {
    inc = inc - 1;
    if ( fanSpeed >= 0 && fanSpeed <= 10 ) {
      speeds[inc] = fanSpeed;
      Serial.print("Fan: ");
      Serial.print(inc);
      Serial.print(" set to ");
      Serial.println(fanSpeed);
    } else {
      Serial.print("fanSpeed out of bounds: ");
      Serial.println(fanSpeed);
    }
  } else {
    Serial.print("inc out of bounds: ");
    Serial.println(inc);
  }

}

// command example: defk
// fans between b-m
void readTemp( uint8_t inc ) {
  Serial.print("Temp ");
  inc = inc + 48;
  inc = inc - 98;
  Serial.print(inc);
  Serial.print(": ");
  if ( inc >= 0 && inc <= 11 ) {
    Serial.println(temperatures[inc]);
  } else {
    Serial.print("inc out of bounds: ");
    Serial.println(inc);
  }
}

void timerSetup() {
  DDRC |= (1 << PC0) | (1 << PC5) | (1 << PC3) ;
  //cli();

  TCCR1A |= (1 << WGM11) | (1 << WGM10);
  TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS10);
  TIMSK1 |= (1 << TOIE1);


  TCNT1 = 0;
  //sei();
}

void setup() {
  Serial.begin(38400);
  Serial.println("setup");
  timerSetup();
}
// A5 PC5
// A0 PC0
// A4 PC3
// A7 ??

void loop() {
  if (Serial.available()) {
    unsigned int incomingByte = Serial.read();
    matchSerialInput(incomingByte, signatureFan, 4, &matchFan, setFan);
    matchSerialInput(incomingByte, signatureTemp, 3, &matchTemp, readTemp);
    extraPar = incomingByte;
  }
}

another quick non related question: does someone know the atmel way of writing a HIGH LOW to ADC7 ?

delay() and delayMicroseconds() use Timer0.

If you have only changed Timer1 that should not be the cause of the problem.

I wonder if the Serial code you have posted is from SoftwareSerial? HardwareSerial won't use delay() for timing.

How often is your code calling TIMER1_OVF_vect - pehaps there isjust not enough time for Serial to work

You may like to look at my Yet Another Software Serial, but I have no idea if it will solve your problem.

...R

I found a nice solution, reading the data sheet properly.

As you can see I am using the timer to generate interrupts.

I adjusted my timer to that and used "normal mode"

void timerSetup() {
 DDRC |= (1 << PC0) | (1 << PC5) | (1 << PC3) ;
 //cli();

 //TCCR1A |= (1 << WGM10);
 //TCCR1A |= (1 << WGM11); 
 //TCCR1B |= (1 << WGM12);
 //TCCR1B |= (1 << WGM13);
 TCCR1B |= (1 << CS10);
 //TCCR1B |= (1 << CS11);
 //TCCR1B |= (1 << CS12);
 TIMSK1 |= (1 << TOIE1);

 TCNT1 = 0;
 //sei();
}