/* Stellt KW1281-Funktionen zur Verfügung
 *
 * 08/2005 Florian Schaeffer

07.2009 uprava Z. Svoboda
*/

#include <avr/io.h>
#include <util/delay.h>
//#include <avr/wdt.h>
#include "kw1281.h"
#include "uart.h"

volatile extern uint8_t mod_kw1281, mod_zobr;

volatile uint8_t  block_cnt,      // für Block Counter ECU<->PC Kommunikation
          block_length;   // für Block length (häßlich aber einfacher, da kein call_by_reference möglich)

void delay_ms(uint16_t ms)
{  
  uint16_t t;
  for(t=0; t<=ms; t++) _delay_ms(1);
}

/**
  @brief  Initialisiert den KW 1281 Controller im 5 Baud 7O1 Modus
      Controller-Nummer fest codiert
      Setzt voraus, daß T1In (TxD) des MAX232 wie üblich an Pin PD1 (TxD) des ATmega8 angeschlossen ist.
  @param  none
  @return none
*/
void kw1281_init (void)
{
 // Adresse 0x01 (1): ECU
  PORTD = PORTD | (1 << PD1);   // PD1 ein  : Vorbereitung
  //wdt_reset();
  delay_ms (1600);
  //wdt_reset();
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus  : Start-Bit 1->0
  delay_ms (200);               // 5Bd = 5 Bits/s => 1000/5 = 200ms/Bit.

  PORTD = PORTD | (1 << PD1);   // PD1 ein
  delay_ms (200);
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus
/*	delay_ms (200);
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus
	delay_ms (200);
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus
	delay_ms (200);
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus
	delay_ms (200);
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus
	delay_ms (200);
  PORTD = PORTD & ~(1 << PD1);  // PD1 aus
	delay_ms (200);
  //wdt_reset();

  PORTD = PORTD & ~(1 << PD1);  // PD1 aus  : Odd Parity
	delay_ms (200);*/
delay_ms (7*200);
  PORTD = PORTD | (1 << PD1);   // PD1 ein  : Stop-Bit
  delay_ms (200);
}

/**
  @brief  Nach dem Controller Init sendet dieser Sync-Code: 55, 01, 8A
  @param  none
  @return bei Erfolg = 1, sonst 0
*/
int8_t kw1281_ecu_sync (void)
{
  uint8_t ecu[3], i;
  for (i=0; i<=2; i++)
  {
    ecu[i] = ser_getc();
  }
  if ((ecu[0] == 0x55) && (ecu[1] == 0x01) && (ecu[2] == 0x8A)) // Sync richtig
  {
    uart_putc (0xFF-ecu[2]);  // Komplement des letzten Bytes als Antwort senden
    ser_getc();         // echo kann unbeachtet bleiben
    return 1;
  }
  else
    return 0;
}

/**
  @brief  Wertet ein empfanges Byte aus und sendet das Komplement dazu an die ECU zurück.
      Dieses Komplement wird als Echo an den µC geschickt, was ignoriert werden kann.
  @param  none
  @return Byte von ECU
*/
uint8_t kw1281_get_byte (void)
{
  uint8_t ecu;

  ecu = ser_getc(); 
  uart_putc (0xFF-ecu); // Komplement schicken
  ser_getc();       // echo ignorieren
  return ecu;
}

/**
  @brief  vysle byte do regulacni jednotky, ignoruje potvrzeni
          a echo
  @param  byte k vyslani
  @return none
*/
void kw1281_give_byte (uint8_t give_byte)
{
  uart_putc (give_byte);
  ser_getc();       // echo ignorieren
  ser_getc();       // Antwort (Komplement) ignorieren
}

/**
  @brief  vysle byte block end do regulacni jednotky, ignoruje echo
  @param  none
  @return none
*/
void kw1281_give_bl_end (void)
{
  uart_putc (0x03);
  ser_getc();        // echo ignorieren, keine weitere Antwort
}

/**
  @brief  posle prikaz
  @param  kod prikaz
  @return none
*/
void kw1281_snd_cmd (uint8_t cmd)
{
  kw1281_give_byte(0x03);
  kw1281_give_byte(++block_cnt);
  kw1281_give_byte(cmd);
  kw1281_give_bl_end();
}

/**
  @brief  Fordert per group reading Daten  an
  @param  zu lesende group Nummer
  @return none
*/
void kw1281_get_grp (uint8_t group)
{
  kw1281_give_byte(0x04);   // Block length
  kw1281_give_byte(++block_cnt);  // Block Counter
  kw1281_give_byte(0x29);   // Ask for group reading
  kw1281_give_byte(group);    // Group  anfordern
  kw1281_give_bl_end();
}

/**
  @brief  vycte datovy blok z RJ
  @param  delka bloku, pole s vyctenymi daty
  @return kod bloku
*/

uint8_t kw1281_get_data (uint8_t *_block_length, uint8_t _values[])
{
  uint8_t title;
  int8_t i;

  *_block_length = kw1281_get_byte();    // Antwort: block length (exluding Block end) - ECU is master
  block_cnt = kw1281_get_byte();     // Antwort: block counter
  title = kw1281_get_byte();        // Block title

  for (i=1; i<=*_block_length-3; i++) // 3 Bytes der block length bereits verarbeitet
  {
    _values[i-1] = kw1281_get_byte();
  }
  ser_getc();       // Block-end Byte ignorieren
  return title;
}
