#ifndef PROMICRO_H
#define PROMICRO_H

// Schnellere Funktionen für den ATmega32U4
// www.gheinz.de

// Inline AVR-Makros für schnelle Pins (Arduino-Pins sind langsam):
// reg can be any AVR-Register like PORTx, PINx, DDRx ... (8 bit)  x = A, B, C, D, ...
// bit is the bit number {0,1,2...7}
// Siehe auch bitSet, bitRead etc. in Arduino.h
#define bitset(reg,bit) ((reg) |= (1 << (bit)))     // bit set    (| OR)
#define bitclr(reg,bit) ((reg) &=~(1 << (bit)))     // bit clear  (& AND; ~ NOT)
#define bittgl(reg,bit) ((reg) ^= (1 << (bit)))     // bit toggle (^ XOR)
#define bitread(reg,bit) (((reg) >> (bit)) & 0x01)  // returns true or false
// Funktion: Das reg (bit) wird auf bit1 geschoben und mit Eins AND-verknüpft
// Syntax:  >> bitshift right;  << bitshift left;  & bitwise AND
// variable << number_of_bits;  variable >> number_of_bits


#ifdef __AVR_ATmega32U4__
// Komfort-Variante schnelles bit-read für ATmega32U4 proMicro:
bool BitRead(int arduino_pin) {
  bool hilo;
  switch(arduino_pin) {
    case 0:  hilo = (bitread(PIND, 2)); break; // PD2 RX
    case 1:  hilo = (bitread(PIND, 3)); break; // PD3 TX
    case 2:  hilo = (bitread(PIND, 1)); break; // PD1
    case 3:  hilo = (bitread(PIND, 0)); break; // PD0
    case 4:  hilo = (bitread(PIND, 4)); break; // PD4
    case 5:  hilo = (bitread(PINC, 6)); break; // PC6
    case 6:  hilo = (bitread(PIND, 7)); break; // PD7
    case 7:  hilo = (bitread(PINE, 6)); break; // PE6
    case 8:  hilo = (bitread(PINB, 4)); break; // PB4
    case 9:  hilo = (bitread(PINB, 5)); break; // PB5
    case 10: hilo = (bitread(PINB, 6)); break; // PB6
    case 11: hilo = (bitread(PINB, 7)); break; // PB7
    case 14: hilo = (bitread(PINB, 3)); break; // PB3
    case 15: hilo = (bitread(PINB, 1)); break; // PB1
    case 16: hilo = (bitread(PINB, 2)); break; // PB2
    case 18: hilo = (bitread(PINF, 7)); break; // PF7
    case 19: hilo = (bitread(PINF, 6)); break; // PF6
    case 20: hilo = (bitread(PINF, 5)); break; // PF5
    case 21: hilo = (bitread(PINF, 4)); break; // PF4
    case 22: hilo = (bitread(PINF, 1)); break; // PF1
    case 23: hilo = (bitread(PINF, 0)); break; // PF0
  }
  return hilo;
}


// Komfort-Variante schnelles bit-set für ATmega32U4 proMicro:
bool BitSet(int arduino_pin) {
  bool hilo;
  switch(arduino_pin) {
    case 0:  hilo = (bitset(PORTD, 2)); break; // PD2 RX
    case 1:  hilo = (bitset(PORTD, 3)); break; // PD3 TX
    case 2:  hilo = (bitset(PORTD, 1)); break; // PD1
    case 3:  hilo = (bitset(PORTD, 0)); break; // PD0
    case 4:  hilo = (bitset(PORTD, 4)); break; // PD4
    case 5:  hilo = (bitset(PORTC, 6)); break; // PC6
    case 6:  hilo = (bitset(PORTD, 7)); break; // PD7
    case 7:  hilo = (bitset(PORTE, 6)); break; // PE6
    case 8:  hilo = (bitset(PORTB, 4)); break; // PB4
    case 9:  hilo = (bitset(PORTB, 5)); break; // PB5
    case 10: hilo = (bitset(PORTB, 6)); break; // PB6
    case 11: hilo = (bitset(PORTB, 7)); break; // PB7
    case 14: hilo = (bitset(PORTB, 3)); break; // PB3
    case 15: hilo = (bitset(PORTB, 1)); break; // PB1
    case 16: hilo = (bitset(PORTB, 2)); break; // PB2
    case 18: hilo = (bitset(PORTF, 7)); break; // PF7
    case 19: hilo = (bitset(PORTF, 6)); break; // PF6
    case 20: hilo = (bitset(PORTF, 5)); break; // PF5
    case 21: hilo = (bitset(PORTF, 4)); break; // PF4
    case 22: hilo = (bitset(PORTF, 1)); break; // PF1
    case 23: hilo = (bitset(PORTF, 0)); break; // PF0
  }
  return hilo;
}

// Komfort-Variante schnelles bit-clear für ATmega32U4 proMicro:
bool BitClear(int arduino_pin) {
  bool hilo;
  switch(arduino_pin) {
    case 0:  hilo = (bitclr(PORTD, 2)); break; // PD2 RX
    case 1:  hilo = (bitclr(PORTD, 3)); break; // PD3 TX
    case 2:  hilo = (bitclr(PORTD, 1)); break; // PD1
    case 3:  hilo = (bitclr(PORTD, 0)); break; // PD0
    case 4:  hilo = (bitclr(PORTD, 4)); break; // PD4
    case 5:  hilo = (bitclr(PORTC, 6)); break; // PC6
    case 6:  hilo = (bitclr(PORTD, 7)); break; // PD7
    case 7:  hilo = (bitclr(PORTE, 6)); break; // PE6
    case 8:  hilo = (bitclr(PORTB, 4)); break; // PB4
    case 9:  hilo = (bitclr(PORTB, 5)); break; // PB5
    case 10: hilo = (bitclr(PORTB, 6)); break; // PB6
    case 11: hilo = (bitclr(PORTB, 7)); break; // PB7
    case 14: hilo = (bitclr(PORTB, 3)); break; // PB3
    case 15: hilo = (bitclr(PORTB, 1)); break; // PB1
    case 16: hilo = (bitclr(PORTB, 2)); break; // PB2
    case 18: hilo = (bitclr(PORTF, 7)); break; // PF7
    case 19: hilo = (bitclr(PORTF, 6)); break; // PF6
    case 20: hilo = (bitclr(PORTF, 5)); break; // PF5
    case 21: hilo = (bitclr(PORTF, 4)); break; // PF4
    case 22: hilo = (bitclr(PORTF, 1)); break; // PF1
    case 23: hilo = (bitclr(PORTF, 0)); break; // PF0
  }
  return hilo;
}
#endif

// AVR-IO's schnell einstellen: z.B. dirreg wie DDRC, portreg wie PORTC

// Input Pullup: dirreg = 0, portreg = 1 :
#define setinputpullup(portreg, dirreg, bit) {((dirreg) &=~(1 << (bit))); ((portreg) |= (1 << (bit)));}

// Output direg:
#define setoutput(dirreg, bit) ((dirreg) |= (1 << (bit)))      // bitset

// Input High-Z dirreg:
#define setinputHiZ(dirreg, bit)  ((dirreg) &=~(1 << (bit))) // bitclr


// Skalierung float
// input x: ADC int, return: double ( Arduinos Funktion map() hat nur int-Ausgabe )
double scale(int x, int in_min, int in_max, double out_min, double out_max) {
  return ((double)(x - in_min)) * (out_max - out_min) / ((double)(in_max - in_min)) + out_min;
}

#endif ///////////////////////////////////
