/*
 * リングバッファ+割り込みを利用したシリアル通信
 * 
 * @author fenrir (M.Naruoka)
 * @since 04/05/30
 * @version 1.0
 */
#include <stdio.h>
#include "AKI3694.h"
#include <common.h>
#include "sci.h"

/* 送信 */
static fifo_char_size_t sci_write(fifo_char_t *, char *, fifo_char_size_t);
static void sci_send(volatile struct st_sci3 *, fifo_char_t *);

/* 受信 */
static fifo_char_size_t sci_read(fifo_char_t *, char *, fifo_char_size_t);
static void sci_recieve(volatile struct st_sci3 *, fifo_char_t *);

/* バッファサイズ */
static fifo_char_size_t sci_fifo_size(fifo_char_t *);

/* エラー処理 */
static void sci_error_handler(volatile struct st_sci3 *);


/**********/
/*  SCI3  */
/**********/
#ifndef SCI3_DISABLE

static fifo_char_t fifo_tx3;
static fifo_char_t fifo_rx3;
static char buffer_tx3[SCI3_TX_BUFFER_SIZE + 1];
static char buffer_rx3[SCI3_RX_BUFFER_SIZE + 1];

/**
 * SCI3を初期化します。
 * 
 */
void sci3_init(){
    fifo_char_init(&fifo_tx3, buffer_tx3, SCI3_TX_BUFFER_SIZE + 1); 
    fifo_char_init(&fifo_rx3, buffer_rx3, SCI3_RX_BUFFER_SIZE + 1); 

    /* SCI3のレジスタ設定はここに書くこと */
 
    /* 通信 全二重通信 
     * 通信モード 調歩同期式モード 
     * クロック 内部クロック 
     * データ長 8bit 
     * パリティ 無 
     * ストップビット長 1bit
     * ビットレート 9600bps(BRR=64@20MHz)
     * 割り込み TXI(送信データエンプティ)、RXI(受信データフル)、ERI(受信エラー)
     */
  SCI3.SCR3.BYTE = 0x00;
    SCI3.SMR.BYTE = 0x00;
    SCI3.BRR = 64;
    int i; for(i = 0; i < 10000; i++);  // 1bit期間待機
    SCI3.SSR.BYTE &= 0x80;  // エラーフラグクリア
    SCI3.SCR3.BYTE |= 0xf0; // 割り込み許可
    IO.PMR1.BIT.TXD = 1;
}

/**
 * SCI3から送信するデータを登録します。
 * 
 * @param data 送信データ
 * @param size 送信データサイズ
 * @return (int) 送信バッファに登録されたデータサイズ
 */
fifo_char_size_t sci3_write(char *data, fifo_char_size_t size){
    fifo_char_size_t _size = sci_write(&fifo_tx3, data, size);
    /* 
     * バッファが空の状態のときTXIは一時的に無効になっているので、
     * それを再度有効にする
     */
    if(_size > 0 && (SCI3.SCR3.BIT.TIE == 0)){SCI3.SCR3.BIT.TIE = 1;}
    return _size;
}

/**
 * SCI3の送信バッファにたまっているデータ量を返します。
 * 
 * @return (int) SCI3の送信バッファにたまっているデータ量
 */
fifo_char_size_t sci3_tx_size(){return sci_fifo_size(&fifo_tx3);}

/**
 * SCI3から受信したデータをもらいます。
 * 
 * @param c 受信したデータを格納するバッファ
 * @param size 受信したデータを格納するバッファのサイズ
 * @return (int) 実際にバッファから読み込んだサイズ
 */
fifo_char_size_t sci3_read(char *c, fifo_char_size_t size){return sci_read(&fifo_rx3, c, size);}

/**
 * SCI3の受信バッファにたまっているデータ量を返します。
 * 
 * @return (int) SCI3の受信バッファにたまっているデータ量
 */
fifo_char_size_t sci3_rx_size(){return sci_fifo_size(&fifo_rx3);}

/* 割り込み処理 */
#pragma interrupt
void int_sci3(){
    /* エラー処理 */
  if(SCI3.SSR.BYTE & 0x38){
    /* フラグクリア */
    SCI3.SSR.BYTE &= ~(0x38);
    sci_error_handler(&SCI3);
  }
  /* 送信データエンプティ */
  if(SCI3.SSR.BIT.TDRE){
    sci_send(&SCI3, &fifo_tx3);
  }
  /* 受信データフル */
  if(SCI3.SSR.BIT.RDRF){
    sci_recieve(&SCI3, &fifo_rx3);
  }
}

#endif /* SCI3_DISABLE */

/************/
/*   汎用   */
/************/

/* 送信 */
static fifo_char_size_t sci_write(fifo_char_t *fifo, char *data, fifo_char_size_t size){
    return fifo_char_write(fifo, data, size); /* リングバッファに書き込み */
}

static void sci_send(volatile struct st_sci3 *sci, fifo_char_t *fifo){
    
    /* 書き込むデータがあるか確認 */
    if(fifo_char_read(fifo, (char *)&(sci->TDR), 1) == 0){
        
        /* 書き込むデータがないので、一時的にTXI割り込みがかからないようにする */
        sci->SCR3.BIT.TIE = 0;
    }
}

/* 受信 */
static fifo_char_size_t sci_read(fifo_char_t *fifo, char *c, fifo_char_size_t size){
    return fifo_char_read(fifo, c, size); /* リングバッファから読み込み */
}

static void sci_recieve(volatile struct st_sci3 *sci, fifo_char_t *fifo){
    fifo_char_write(fifo, (char *)&(sci->RDR), 1); /* リングバッファに1バイト書き出し */
}

/* バッファサイズ */
static fifo_char_size_t sci_fifo_size(fifo_char_t *fifo){
    return fifo_char_size(fifo);
}

/* エラー処理 */
static void sci_error_handler(volatile struct st_sci3 *sci){
    
}