#include "m31820.h"

typedef struct {
  uint8_t sign;
  uint8_t integer_part;
  uint16_t float_part;
} temp_float_t;

temp_float_t temp_float[D1W_ASYNC_MAX_DEVICES];
uint8_t      is_m31820[D1W_ASYNC_MAX_DEVICES];

uint8_t inited = 0;

void D1W_device_register(uint8_t rnk,uint64_t id){
  uint8_t i;
  if(! inited){
    inited = 1;
    for(i=0;i<D1W_ASYNC_MAX_DEVICES;i++){
      temp_float[i].sign=0;
      temp_float[i].integer_part=0;
      temp_float[i].float_part=0;
      is_m31820[i]=0;      
    }
  }
  if((id & 0xff) == 0x28){
    // family code in the rom
    is_m31820[rnk]=1;
    printstr_blocking(USART1," as an m31820");
  }
  
}

void m31820_set_temp(uint8_t id, uint64_t val){
  uint8_t tlsb = *((uint8_t*) &val);
  uint8_t tmsb = *(((uint8_t*) &val)+1);

  // datasheet p 6
  if(tmsb & 0x80){
  // negative temp
  temp_float[id].sign=1;
  tmsb = ~tmsb;
  tlsb = ~tlsb;       
  }else{
  // positive temp
  temp_float[id].sign=0;
  }
  temp_float[id].integer_part = (tmsb << 4) | (tlsb >>4);
  temp_float[id].float_part   = (tlsb & 7) * 625;
}

void m31820_print_temp(uint32_t usart,uint8_t id){

  m31820_set_temp(id, D1W_getdevicevalue(id));

  if(temp_float[id].sign)
    printstr_blocking(usart,"-");
  print_uint(usart,temp_float[id].integer_part);
  if(temp_float[id].float_part){
    printstr_blocking(usart,".");
    if(temp_float[id].float_part<1000)
      printstr_blocking(usart,"0");
    print_uint(usart,temp_float[id].float_part);

  }
}


uint8_t w_readtempstep = 0;
uint8_t D1W_device_command_evt_handler_M31820_CONVERT(D1W_event * evt,uint8_t initial){
  switch(evt->event){
  case C_PRESENCE_DETECT_SUCCESS:
    D1W_async_portwrite8(evt->port_id,D1W_MATCH_ROM);

    return 0;
    break;
  case C_WRITING_DONE:
    switch(w_readtempstep){
    case 0:
      D1W_async_portwrite64(evt->port_id,evt->value);
      w_readtempstep=1;
      return 0;
      break;
    case 1:
      D1W_async_portwrite8(evt->port_id,M31820_CONVERT);
      w_readtempstep=2;
      return 0;
      break;
    case 2:
      // we have to wait
      D1W_async_act_next_in_long(evt->port_id,TCONV_9BITS);
      w_readtempstep=3;
      return 0;
      break;
    case 3:
      D1W_async_portwrite64(evt->port_id,evt->value);
      w_readtempstep=4;
      return 0;
      break;
    case 4:
      D1W_async_portwrite8(evt->port_id,M31820_READ_SCRATCHPAD);
      w_readtempstep=5;
      return 0;
      break;
    case 5:
      D1W_async_portread64(evt->port_id);
      w_readtempstep=6;
      return 0;
      break;
    }
  case C_READING_DONE:
    w_readtempstep=0;
   
    return 1;
    break;
  
  case N_LONGWAIT:
    
    D1W_async_start_controler_presence_detect(evt->port_id);
    return 0;
    break;
  }
}

uint8_t w_scratchstep = 0;
uint8_t D1W_device_command_evt_handler_M31820_WRITE_SCRATCHPAD(D1W_event * evt,uint8_t initial){
  // ignore the value, use less precision ,faster

  switch(evt->event){
  case C_WRITING_DONE:
    switch(w_scratchstep){
    case 0:
      D1W_async_portwrite64(evt->port_id,evt->value);
      w_scratchstep=1;
      return 0;
    case 1:
    case 2:
      D1W_async_portwrite8(evt->port_id,0);
      w_scratchstep++;
      return 0;
      break;
    case 3:
      D1W_async_portwrite8(evt->port_id,M31820_CONFIG_9BITS);
      w_scratchstep++;
      return 0;
      break;
    case 4:
      D1W_async_start_controler_presence_detect(evt->port_id);
      w_scratchstep=0;
      return 1;
      break;
    }
  case C_PRESENCE_DETECT_SUCCESS:
    D1W_async_portwrite8(evt->port_id,D1W_MATCH_ROM);
    w_scratchstep=0;
    return 0;
    break;

  }
}

uint8_t D1W_device_command_evt_handler(uint8_t protocmd,D1W_event * evt,uint8_t initial){
  uint8_t val = evt->value;
  switch(protocmd){
  case M31820_WRITE_SCRATCHPAD:
    return D1W_device_command_evt_handler_M31820_WRITE_SCRATCHPAD(evt,initial);
    break;
  case M31820_CONVERT:
    return D1W_device_command_evt_handler_M31820_CONVERT(evt,initial);
    break;

  }
}

/*
  void m31820_conv(uint8_t num,uint8_t bits,uint64_t rom){
  uint8_t conf;
  uint16_t tconv;
  uint64_t scratchpad;
  uint8_t crc;
  uint32_t t;
  D1W_write8(num,M31820_WRITE_SCRATCHPAD);
  D1W_write8(num,0);
  D1W_write8(num,0);    
  switch(bits){
  case 9:
  tconv = TCONV_9BITS;
  conf = M31820_CONFIG_9BITS;
  break;
  case 10:
  tconv= TCONV_10BITS;
  conf = M31820_CONFIG_10BITS;
  break;
  case 11:
  tconv = TCONV_11BITS;
  conf = M31820_CONFIG_11BITS;
  break;
  case 12:
  tconv = TCONV_12BITS;
  conf = M31820_CONFIG_12BITS;
  break;
  }
  D1W_write8(num,conf);
  D1W_detect_presence(num);
  D1W_matchrom(num,rom);
  D1W_write8(num,M31820_CONVERT);
  D1W_blockfor_ms(num,tconv);
  D1W_detect_presence(num);
  D1W_matchrom(num,rom);
  D1W_write8(num,M31820_READ_SCRATCHPAD);
  scratchpad = D1W_read64(num);
  crc =  D1W_read8(num);
  if(crc == D1W_getcrc(((uint8_t*)&scratchpad),8)){
  uint8_t tlsb = *((uint8_t*) &scratchpad);
  uint8_t tmsb = *(((uint8_t*) &scratchpad)+1);

  // datasheet p 6
  if(tmsb & 0x80){
  // negative temp
  temp_float.sign=1;
  tmsb = ~tmsb;
  tlsb = ~tlsb;       
  }else{
  // positive temp
  temp_float.sign=0;
  }
  temp_float.integer_part = (tmsb << 4) | (tlsb >>4);
  temp_float.float_part   = (tlsb & 7) * 625;
        
  printstr_blocking(USART1,"temperature read :");
  m31820_print_float(USART1);
  printstr_rn(USART1);
  }


  
  
  
  }

  uint32_t m31820_get_temp(uint8_t num,uint8_t id){
  uint64_t rom =  D1W_get_rom(id);
  if(!rom)
  return -1;
  GPIOC_ODR ^= (1<<13);
  GPIOC_ODR ^= (1<<13);
  D1W_detect_presence(num);
  D1W_matchrom(num,rom);
  m31820_conv(num,12,rom);
  


  }
*/
