/** Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 */

/** @file
 * @defgroup uart_example_main main.c
 * @{
 * @ingroup uart_example
 * @brief UART Example Application main file.
 *
 * This file contains the source code for a sample application using UART.
 * 
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
//DS18B20 stuff
#include "app_timer.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_timer.h"
#include "string.h"

//#define ENABLE_LOOPBACK_TEST  /**< if defined, then this example will be a loopback test, which means that TX should be connected to RX to get data loopback. */

#define MAX_TEST_DATA_BYTES     (15U)                /**< max number of test bytes to be used for tx and rx. */
//#define UART_TX_BUF_SIZE 256                         /**< UART TX buffer size. */
//#define UART_RX_BUF_SIZE 1                           /**< UART RX buffer size. */
#define UART_TX_BUF_SIZE 1024                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 1024                           /**< UART RX buffer size. */

//DS18B20 stuff
#define DS18B20PIN 4

void ds18b20_read(void * data_ptr, unsigned int num_bytes)
{
  char  ch; //Current reading byte buffer
  char * data_buf = data_ptr;
  
  int i=0,u=0;
  for (i=0;i<num_bytes;i++)
  {
    ch=0;
    for(u=0;u<8;u++)
    {
      //Form read slot
      nrf_gpio_cfg_output(DS18B20PIN);
      nrf_gpio_pin_write(DS18B20PIN,0);
      nrf_delay_us(5);
      nrf_gpio_cfg_input(DS18B20PIN, NRF_GPIO_PIN_NOPULL);
      nrf_delay_us(5);
      if(nrf_gpio_pin_read(DS18B20PIN)>0)
      {
        ch |= 1 << u; //There is 1 on the bus
      }
      else
      {
        ch &= ~(1 << u); //There us 0 on the bus
      }

      //Apply "long" timer for make sure that timeslot is end
      nrf_delay_us(60);
    }
    data_buf[i]=ch;
  }
  nrf_gpio_cfg_input(DS18B20PIN, NRF_GPIO_PIN_NOPULL);
}

void ds18b20_write(void * data_ptr, unsigned int num_bytes)
{
  char  ch; //Current reading byte buffer
  char * data_buf = data_ptr;
  
  int i=0,u=0;
  for (i=0;i<num_bytes;i++)
  {
    ch=data_buf[i];
    for(u=0;u<8;u++)
    {
      //Form write slot
      nrf_gpio_cfg_output(DS18B20PIN);
      nrf_gpio_pin_write(DS18B20PIN,0);
      nrf_delay_us(1);
      //write 1 - pull bus to HIGH just after short timer
      if(ch&(1<<u))
      {
        nrf_gpio_cfg_input(DS18B20PIN, NRF_GPIO_PIN_NOPULL); 
      }
      //Apply "long" timer for make sure that timeslot is end
      nrf_delay_us(60);
      //Release bus, if this wasn't done before
      nrf_gpio_cfg_input(DS18B20PIN, NRF_GPIO_PIN_NOPULL);
      data_buf[i]=ch;
    }
  }
  nrf_gpio_cfg_input(DS18B20PIN, NRF_GPIO_PIN_NOPULL);
}

//Perform reset of the bus, and then wait for the presence pulse
bool ds18b20_reset_and_check(void)
{
  int res=0;
  //Form reset pulse
  
  nrf_gpio_cfg_output(DS18B20PIN);
  nrf_gpio_pin_write(DS18B20PIN,0);
  nrf_delay_us(500);
  //Release bus and wait 15-60MS
  nrf_gpio_cfg_input(DS18B20PIN, NRF_GPIO_PIN_NOPULL);
  nrf_delay_us(60);

  //Read from bus
  res=nrf_gpio_pin_read(DS18B20PIN);
  if(res==0)
  {
    nrf_delay_us(500);
    return true;
  }
  return false;
}
/**
 *@}
 **/

int16_t ds18b20_read_temp(void)
{
   char buf[16];
    //double f;
        //int i;
     int16_t raw_temp=0;

    ds18b20_reset_and_check();

//Read ROM
    buf[0]=0x33;
    ds18b20_write(&buf,1);

//Read the results
    
    ds18b20_read(&buf,8);
    memset(&buf,0,16);

    //Send convert TX cmd
    buf[0]=0x44; //Convert temp
    ds18b20_write(&buf,1);
    nrf_delay_ms(1000);//Wait for finishing of the conversion

    ds18b20_reset_and_check();
    buf[0]=0x33; //Read ROM
    ds18b20_write(&buf,1);
    //Read the results
    ds18b20_read(&buf,8);
    memset(&buf,0,16);
    buf[0]=0xBE;  //Read scratchpad
    ds18b20_write(&buf,1);
    //Read the results
    ds18b20_read(&buf,9);
    //raw_temp = (buf[1] << 4) | (buf[0] >> 4);
    raw_temp = (buf[1] << 8) | buf[0];

    //memcpy(&f,&buf,8);
    //f=(float)raw_temp / 16.0;
    return(raw_temp);
}

void uart_error_handle(app_uart_evt_t * p_event)
{
    if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_communication);
    }
    else if (p_event->evt_type == APP_UART_FIFO_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_code);
    }
}



#ifdef ENABLE_LOOPBACK_TEST
/** @brief Function for setting the @ref ERROR_PIN high, and then enter an infinite loop.
 */
static void show_error(void)
{
    
    LEDS_ON(LEDS_MASK);
    while(true)
    {
        // Do nothing.
    }
}


/** @brief Function for testing UART loop back. 
 *  @details Transmitts one character at a time to check if the data received from the loopback is same as the transmitted data.
 *  @note  @ref TX_PIN_NUMBER must be connected to @ref RX_PIN_NUMBER)
 */
static void uart_loopback_test()
{
    uint8_t * tx_data = (uint8_t *)("\n\rLOOPBACK_TEST\n\r");
    uint8_t   rx_data;

    // Start sending one byte and see if you get the same
    for (uint32_t i = 0; i < MAX_TEST_DATA_BYTES; i++)
    {
        uint32_t err_code;
        while(app_uart_put(tx_data[i]) != NRF_SUCCESS);

        nrf_delay_ms(10);
        err_code = app_uart_get(&rx_data);

        if ((rx_data != tx_data[i]) || (err_code != NRF_SUCCESS))
        {
            show_error();
        }
    }
    return;
}


#endif


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    //LEDS_CONFIGURE(LEDS_MASK);
    //LEDS_OFF(LEDS_MASK);
    //DS18B20 stuff
    uint32_t err_code;
    err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    int16_t raw_temp;

    const app_uart_comm_params_t comm_params =
      {
          RX_PIN_NUMBER,
          TX_PIN_NUMBER,
          RTS_PIN_NUMBER,
          CTS_PIN_NUMBER,
          APP_UART_FLOW_CONTROL_ENABLED,
          false,
          UART_BAUDRATE_BAUDRATE_Baud115200
      };

    APP_UART_FIFO_INIT(&comm_params,
                         UART_RX_BUF_SIZE,
                         UART_TX_BUF_SIZE,
                         uart_error_handle,
                         APP_IRQ_PRIORITY_LOW,
                         err_code);

    APP_ERROR_CHECK(err_code);
/*
#ifndef ENABLE_LOOPBACK_TEST
    printf("\n\rStart: \n\r");

    while (true)
    {
        uint8_t cr;
        while(app_uart_get(&cr) != NRF_SUCCESS);
        while(app_uart_put(cr) != NRF_SUCCESS);

        if (cr == 'q' || cr == 'Q')
        {
            printf(" \n\rExit!\n\r");

            while (true)
            {
                // Do nothing.
            }
        }
    }
#else

    // This part of the example is just for testing the loopback .
    while (true)
    {
        uart_loopback_test();
    }
#endif
*/
    printf("\n\rStart: \n\r");
  while(true)
  {
    raw_temp = ds18b20_read_temp();
    printf("%c%c\r\n", raw_temp >> 8, raw_temp & 0xff);
    //nrf_delay_ms(100);
    //app_uart_put(raw_temp >> 8);
    //app_uart_put(raw_temp & 0xff);
    //printf("read temp: %i.%i \r\n", raw_temp >> 4, (int)(((raw_temp & 0xf) >> 0)*6.25));
  }


}


/** @} */
