//*******************************************************************
//Date: 09.04.2008
//Autor: Eugene Samoylov
//Descr: Модуль работы со TouchMemory
//*******************************************************************

#include <avr/io.h>
#include "type.h"

#include "delay1.c"
#include "delay1.h"
#include "TouchMemory.h"


#define     clkMhz    8 // частота шины в МГЦ


//******************************************************************************
//  Функция подсчёта CRC для полинома {10011001} (протокол iButton)
//******************************************************************************
BYTE CRC_calc(BYTE *data)
{//uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data)
BYTE j, i, crc = 0;

    for(j = 0; j < 8; j ++)
    {
        crc = crc ^ data[j];
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x01) crc = (crc >> 1) ^ 0x8C;
            else            crc >>= 1;
        }
    }
return crc;
}

//******************************************************************************
//          Функция чтения ключа iButton
// input:
// *code - указатель на буфер для ключа 8 байт
// TM - пин регистра ввода вывода откуда производится чтение
// output:
// 0 - ок;
// 1 - нет импульса присутствия;
// 2 - ненормальное состояние линии (КЗ?)
// 3 - ошибка CRC
//******************************************************************************
BYTE ReadKey(BYTE *code, BYTE TM)
{
BYTE tcnt, Data, i;

  // импульс сброса
  SETBIT(DDR_TM,  TM);                    // выход
  CLRBIT(PORT_TM, TM);                    // низкий уровень
  __delay_cycles(clkMhz * 500);           // 500 мкс низкого уровня
  CLRBIT(DDR_TM,  TM);                    // вход
  SETBIT(PORT_TM, TM);                    // c подтяжкой

  // детектирования импульса присутствия
  tcnt = 0;
  __delay_cycles(clkMhz * 10);
  while(PIN_TM & (1 << TM))
  {
  __delay_cycles(clkMhz * 10);
  tcnt ++;
  // если нет - выходим
  if(tcnt > 10) return 1;
  }

  // детектирования готовности ключа
  tcnt = 0;
  __delay_cycles(clkMhz * 10);
  while(!(PIN_TM & (1 << TM)))
  {
  __delay_cycles(clkMhz * 20);
  tcnt ++;
  // если линия все еще в низком уровне - гдето КЗ
  if(tcnt > 15) return 2;
  }

  __delay_cycles(clkMhz * 20);
  Data = 0x33;
  // если да - передача команды
  for(tcnt = 0; tcnt < 8; tcnt ++)
  {
    if(!(Data & (1 << tcnt)))
    {
    // если 0 сформировать задний фронт + 60 мкс + передний фронт
      SETBIT(DDR_TM,  TM);                    // выход
      CLRBIT(PORT_TM, TM);                    // низкий уровень
      __delay_cycles(clkMhz * 90);
      SETBIT(PORT_TM, TM);                    // высокий уровень
    }
    else
    {
    // если 1 сформировать задний фронт + 15 мкс + передний фронт + 45 мкс
      SETBIT(DDR_TM,  TM);                    // выход
      CLRBIT(PORT_TM, TM);                    // низкий уровень
      __delay_cycles(clkMhz * 8);
      SETBIT(PORT_TM, TM);                    // высокий уровень
      __delay_cycles(clkMhz * 80);
    }
  __delay_cycles(clkMhz * 10);
  }

  // чтение данных
  for(i = 0; i < 8; i++) // байтовый цикл
  {

    Data = 0;

    for(tcnt = 0; tcnt < 8; tcnt ++)          // битовый цикл
    {
    // даем строб 5 мкс
      SETBIT(DDR_TM,  TM);                    // выход
      CLRBIT(PORT_TM, TM);                    // низкий уровень
      __delay_cycles(clkMhz * 13); //было 5
    // переключаемся на вход с подтяжкой
      CLRBIT(DDR_TM,  TM);                    // вход
      SETBIT(PORT_TM, TM);                    // подтяжка
    // ждем 10 мкс
      __delay_cycles(clkMhz * 2); //было 15 !!!
    // читаем данные
      Data >>=1;                            // сдвигаем рег.данных
      if(PIN_TM & (1 << TM))
      {
      Data |= (1 << 7);// 1
      }
    __delay_cycles(clkMhz * 55); //было 45 !!!
    }

    code[i] = Data;
  }

  // проверка CRC
  if (CRC_calc(code) == 0)
  {
    return 0;
  }

return 3;
  // выходим
}
