/*!
  \file
  \brief mot ファイルの受信と書き込み

  \author Satofumi KAMIMURA

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

#include "tiny_sci.h"
#include "flash.h"
#include "jump.h"

enum {
  False = 0,
  True = 1,
};


static unsigned long decode32(const char *buffer)
{
  return
    ((buffer[0] << 24) & 0xff000000) | ((buffer[1] << 16) & 0x00ff0000) |
    ((buffer[2] << 8) & 0x0000ffff) | (buffer[3] & 0x000000ff);
}


static int checkSum(const char *buffer, int packet_size)
{
  char actual_sum = 0;
  int n = packet_size - 1;
  int i;

  for (i = 0; i < n; ++i) {
    actual_sum += buffer[i];
  }
  return (actual_sum == buffer[n]) ? True : False;
}


void sformat_handler(void)
{
  enum {
    DefaultPacketSize = 1 + 4 + 1,
    DataPacketSize = 1 + 32 + 1,
    MaxPacketSize = DataPacketSize,
  };
  char buffer[MaxPacketSize];
  unsigned long address = 0x00000000;

  while (1) {
    int packet_size = DefaultPacketSize;
    char packet_type;
    char reply_ch;

    // パケットタイプの読み出し
    sci_gets(buffer, 1);
    packet_type = buffer[0];

    if (packet_type == 'D') {
      packet_size = DataPacketSize;
    }

    // 続きのデータを読み出し
    sci_gets(&buffer[1], packet_size - 1);

    // チェックサムの確認
    if (! checkSum(buffer, packet_size)) {
      sci_putch('E');
      return;
    }

    reply_ch = 'E';
    switch (packet_type) {
    case 'B':
      // Baudrate コマンドの処理
      sci_putch('A');
      sci_setBaudrate(decode32(&buffer[1]));
      continue;
      break;

    case 'A':
      // Address コマンドの処理
      address = decode32(&buffer[1]);
      reply_ch = 'A';
      break;

    case 'D':
      // Data コマンドの処理
      reply_ch = (flash_data(address, &buffer[1]) == 0) ? 'A' : 'E';
      address += 32;
      break;

    case 'J':
      // Jump コマンドの処理
      jump(decode32(&buffer[1]));
      break;
    }
    sci_putch(reply_ch);
  }
}
