/*
 * File:   newmain.c
 * Author: autoelectric
 *
 * Created on 11 Июнь 2014 г., 13:37
 */
#include <p18cxxx.h>
#include <delays.h>
#include <usart.h>
#pragma config OSC=IRCIO67
#pragma config FCMEN=OFF
#pragma config IESO=OFF
#pragma config PWRT=OFF
#pragma config BOREN=OFF
#pragma config BORV=3
#pragma config WDT=OFF
#pragma config WDTPS=32768
#pragma config PBADEN=OFF
#pragma config LPT1OSC=OFF
#pragma config MCLRE=OFF
#pragma config STVREN=ON
#pragma config LVP=OFF
#pragma config BBSIZ=1024
#pragma config XINST=OFF
#pragma config CP0=OFF
#pragma config CP1=OFF
#pragma config CPB=OFF
#pragma config CPD=OFF
#pragma config WRT0=OFF
#pragma config WRT1=OFF
#pragma config WRTC=OFF
#pragma config WRTB=OFF
#pragma config WRTD=OFF
#pragma config EBTR0=OFF
#pragma config EBTR1=OFF
//###################################################################
#define tris_dallas     TRISAbits.TRISA3
#define dallas          LATAbits.LATA3
#define dallas_port     PORTAbits.RA3
//###################################################################
#pragma udata
char dallas_ok[]="OK";
char dallas_error[]="Error";
char DRomBuf[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
char DRomBufASCII[17];
char DTemp[2]={0x00,0x00};
char com_reg,error_dallas;
char con_dallas=0;

char RxIn[30]={0};
int  WaitTimer1=0;
char incRxIn=0;
//*********************************************************
#pragma code
void MyHighInt(void);
#pragma interrupt MyHighInt
#pragma code high_vector=0x08
void high_vector(void){
    _asm GOTO MyHighInt _endasm
}
#pragma code
void SendStringUSART(char*);
//**********Прототипы функций для датчика температуры***************
void  Delay480us(void);
void  Delay60us(void);
void  HowDelay(int);
char  ResetDallas(void);
void  DoutLow(void);
void  DoutHigh(void);
char  DRecive(void);
void  DSend(char);
char* HexToASCII(char*,char*,int );
void  DReadRom(void);
char* DGetTemp(void);
void main(void)
{
    ADCON1=0;
    ADCON1=0x0f;
    OSCCONbits.SCS0=0;
    OSCCONbits.SCS1=0;
    OSCCONbits.IRCF0=0;
    OSCCONbits.IRCF1=1;
    OSCCONbits.IRCF2=1;
    OSCTUNEbits.PLLEN=1;
    baudUSART(BAUD_16_BIT_RATE&BAUD_WAKEUP_OFF&BAUD_AUTO_OFF);
    OpenUSART( USART_TX_INT_OFF&USART_RX_INT_ON&USART_ASYNCH_MODE
            &USART_EIGHT_BIT &USART_CONT_RX &USART_BRGH_LOW,25);//38400
    RCONbits.IPEN=0;
    INTCONbits.GIE=1;
    INTCONbits.PEIE=1;
////////////////////////////////////////////////////////////////////////////////
    while(1)
    {
       ResetDallas();
       if(error_dallas){                 //Если датчик не ответил
           SendStringUSART(dallas_error);
       }
       else{                             //Если датчик ответил
           SendStringUSART(dallas_ok);
       }
       DReadRom();                                      //Читаем ROM
       SendStringUSART(HexToASCII(DRomBuf,DRomBufASCII,8));
       HowDelay(2);                                    //Здаржка на большое время
       SendStringUSART(HexToASCII(DGetTemp(),DRomBufASCII,2)); //2 байта -старший ,затем младший в Hex
       HowDelay(4);
    }
////////////////////////////////////////////////////////////////////////////////
}
void MyHighInt(void)
{
    if(PIR1bits.RCIF)
    {
        RxIn[incRxIn++]=getcUSART();
        if(incRxIn>13)
            incRxIn=0;
        PIR1bits.RCIF=0;
    }
}
void SendStringUSART(char* str)
{
    int i=0;
    while(str[i])
    {
        while(!TXSTAbits.TRMT);
        putcUSART(str[i]);
        i++;
    }
    while(!TXSTAbits.TRMT);
    putcUSART(0x0D);
}
//Функция возвращает адрес массива символов в памяти, куда запишет
//преобразованные в строку шеснадцатиричные значения байтов в массиве,
//переданном ей параметром sour(адрес массива байтов, который надо преобразовать)
//len -колличество байтов в sour,dest-адрес массива, куда запишем преобразованную
//строку, равную len*2.
char* HexToASCII(char *sour,char *dest,int len)
{
    int i;
    char tmp;
     int j=0;
    for(i=0;i<len;i++){
        tmp=((sour[i]>>4)&0x0f);
        if(tmp<=9){
            dest[j]=tmp+0x30;
        }
        else if(tmp>=0x0A && tmp<=0x0F){
            dest[j]=tmp+0x37;
        }
        j++;
        tmp=sour[i];
        tmp=tmp &= 0x0f;
        if(tmp<=9){
            dest[j]=tmp+0x30;
        }
        else if(tmp>=0x0A && tmp<=0x0F){
            dest[j]=tmp+0x37;
        }
        j++;


    }
    dest[j]=0;
    return dest;
}
//**********Функции для работы с датчиком температуры****************
char ResetDallas(void){                  //Сброс датчика
    char err=1;
    error_dallas=1;
    DoutLow();
    Delay480us();
    DoutHigh();
    Delay60us();
    if(!dallas_port){
        error_dallas=0;
        err=0;
    }
    Delay480us();
    return err;
}
//Чтение ROM датчика - сохраняет 8 байт ROM датчика в массиве DRomBuf[7]
void DReadRom(void){
    int i;
    int j=0;
    DoutLow();
    DoutHigh();
    if(!dallas_port){
        return;
    }
    if(ResetDallas()){
        return;
    }
    DSend(0x33);
    for(i=0;i<8;i++){
        DRomBuf[i]=DRecive();
    }
}
//Измеряем и читаем температуру из одного датчика
char* DGetTemp(void){
    int i;
    int j=0;
    DoutLow();
    DoutHigh();
    if(!dallas_port)return DTemp;
    if(con_dallas)goto READ;
    if(ResetDallas()) return DTemp;
    DSend(0xCC);
    DSend(0x44);
    con_dallas=1;
    return DTemp;
READ:
    con_dallas=0;
    if(ResetDallas())return DTemp;
    DSend(0xCC);
    DSend(0xBE);
    DTemp[1]=DRecive();
    DTemp[0]=DRecive();
    return DTemp;
}
//Функции протокола 1-wire
void DoutLow(void){          //устанавливает линию передачи в 0
    dallas=0;
    tris_dallas=0;
    Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
    Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
    Nop();Nop();Nop();Nop();
}
void DoutHigh(void){         //отпускает линию в 1 (+5В от резистора)
    tris_dallas=1;
    Nop();Nop();Nop();Nop();Nop();Nop();
}
//Принимает байт
char DRecive(void){
    int i;
    for(i=0;i<8;i++){
        DoutLow();
        DoutHigh();
        if(dallas_port){
            STATUSbits.C=1;
        }
        else{
            STATUSbits.C=0;
        }
        Rrcf(com_reg,1,1);
        Delay60us();
    }
    return com_reg;
}
//Передает байт далласу
void DSend(char data){
    int i;
    com_reg=data;
    for(i=0;i<8;i++){
        DoutLow();
        Rrcf(com_reg,1,1);
        if(STATUSbits.C){
            DoutHigh();
        }
        else{
            DoutLow();
        }
        Delay60us();
        DoutHigh();
    }
}
//Функции задержки
void Delay480us(void){
    Delay100TCYx(19);
    Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
    Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();
    Nop();Nop();Nop();Nop();
}
void Delay60us(void){
    Delay10TCYx(24);
}
void HowDelay(int i){
    int j=0;
    for(;j<i;j++){
        Delay10KTCYx(0);
    }
}