#include "stm32f0xx.h"
#include "uart.h"
#include "utils.h"
#include "owi.h"

const uint8_t ibutton_code[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // secret, true values are not mentioned

void owi_init(void)
{
	GPIOA->MODER |= (2 << GPIO_MODER_MODER2_Pos)|(2 << GPIO_MODER_MODER3_Pos); // PA2, PA3 alternate function
	GPIOA->OTYPER |= GPIO_OTYPER_OT_2; // PA2 open drain
	GPIOA->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEEDR2_Pos)|(3 << GPIO_OSPEEDR_OSPEEDR3_Pos); // high speed
	GPIOA->AFR[0] |= (1 << GPIO_AFRL_AFRL2_Pos)|(1 << GPIO_AFRL_AFRL3_Pos); // used by USART1

	// 8 bits, 1 stop bit, no parity
	USART1->CR3 |= (1 << USART_CR3_OVRDIS_Pos); // overrun disable
	USART1->CR1 |= (1 << USART_CR1_TE_Pos)|(1 << USART_CR1_RE_Pos); // transmitter, receiver enable
}

uint8_t owi_authorisation(void)
{
  uint8_t i, j;

  for(i = 0; i < 3; i++)
  {
    if(owi_presence())
    {
      delay_ms(1);
      owi_write_byte(0x33); // read ROM
      for(j = 0; j < 8; j++)
      {
        delay_ms(1);
        if(owi_read_byte() != ibutton_code[j])
          return 0;
      }

      return 1;
    }
    else
      delay_ms(100);
  }

  return 0;
}

uint8_t owi_presence(void)
{
  USART1->CR1 &= ~(1 << USART_CR1_UE_Pos); // disable usart
	USART1->BRR = 3333; // change baudrate to 9600 @ 32 MHz
	USART1->CR1 |= (1 << USART_CR1_UE_Pos); // enable usart

	uart_send(0xF0);
	if(uart_receive() != 0xF0)
		return 1;
	else
		return 0;
}

void owi_write_byte(uint8_t data)
{
	uint8_t i;

	USART1->CR1 &= ~(1 << USART_CR1_UE_Pos); // disable usart
	USART1->BRR = 278; // change baudrate to 115200 @ 32 MHz
	USART1->CR1 |= (1 << USART_CR1_UE_Pos); // enable usart

	for(i = 0; i < 8; i++)
	{
		if(data & 0x01)
			uart_send(0xFF);
		else
			uart_send(0x00);

		data >>= 1;
	}
}

uint8_t owi_read_byte(void)
{
	uint8_t i;
	uint8_t data = 0;

	/*
	USART1->CR1 &= ~(1 << USART_CR1_UE_Pos); // disable usart
	USART1->BRR = 278; // change baudrate to 115200 @ 32 MHz
	USART1->CR1 |= (1 << USART_CR1_UE_Pos); // enable usart
	*/

	for(i = 0; i < 8; i++)
	{
		USART1->RQR |= (1 << USART_RQR_RXFRQ_Pos); // flush rx fifo
		data >>= 1;
		uart_send(0xFF);
		if(uart_receive() == 0xFF)
			data |= 0x80;
	}

	return data;
}
