/*!
  \file
  \brief SCI 操作

  \author Satofumi KAMIMURA

  $Id: tiny_sci.c 1111 2009-07-05 21:06:28Z satofumi $
*/

#include "tiny_sci.h"
#include "cpu_aki_sh2.h"


enum {
  MaxBaudrate = 115200,
  SCI_BIT_WAIT = (int)(CPU_CLOCK / MaxBaudrate),
};


int sci_setBaudrate(long baudrate)
{
  volatile int i;

  switch (baudrate) {

  case 9600:
    SCI1.BRR = 92;
    break;

  case 19200:
    SCI1.BRR = 46;
    break;

  case 38400:
    SCI1.BRR = 22;
    break;

  case 57600:
    SCI1.BRR = 15;
    break;

  case 115200:
    SCI1.BRR = 7;
    break;

  default:
    return -1;
  }

  /* wait 1 bit */
  for (i = 0; i < SCI_BIT_WAIT; ++i) {
    ;
  }

  return 0;
}


void sci_initialize(long baudrate)
{
  SCI1.SCR.BYTE = 0x00;
  SCI1.SMR.BYTE = 0;                /* 8bit, 1stop, no parity */
  sci_setBaudrate(baudrate);
  PFC.PACRL2.WORD |= 0x0140;        /* enable RxD1, TxD1 */
  SCI1.SCR.BYTE = 0x30;                /* TE = 1, RE = 1 */
  SCI1.SSR.BYTE &= ~0x40;
}


char sci_getch(void)
{
  char ch = '\0';

  while (1) {
    if (SCI1.SSR.BYTE & 0x38) {
      // 受信エラー
      SCI1.SSR.BYTE &= ~0x38;
      break;

    } else if (SCI1.SSR.BYTE & 0x40) {
      ch = SCI1.RDR;
      SCI1.SSR.BYTE &= ~0x40;
      break;
    }
  }

  return ch;
}


void sci_gets(char *buffer, int len)
{
  int i;

  for (i = 0; i < len; ++i) {
    buffer[i] = sci_getch();
  }
}


void sci_flush(void)
{
  /* TEND */
  while ((SCI1.SSR.BYTE & 0x04) == 0) {
    ;
  }
}


void sci_putch(char ch)
{
  /* TDRE */
  while ((SCI1.SSR.BYTE & 0x80) == 0) {
    ;
  }
  SCI1.TDR = ch;
  SCI1.SSR.BYTE  &= ~0x80;
}


void sci_puts(const char* str)
{
  for (; *str != '\0'; ++str) {
    sci_putch(*str);
  }
}
