/*
 *
 */

#include <Utils.h>
#include "HL_gio.h"
#include "HL_reg_gio.h"
#include "HL_sci.h"
#include "HL_reg_sci.h"

#include "HL_esm.h"


static char ASCII[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

void Puts(const char *const str) {
  char *ptr;
  ptr = (char *)str;
  while(*ptr) {
    sciSendByte(sciREG1,*ptr++);
  }
}

void PutH64(const uint64 val){
  int shift;
  sciSendByte(sciREG1,'0');
  sciSendByte(sciREG1,'x');
  for(shift=64-4;shift>=0;shift-=4) {
    sciSendByte(sciREG1,ASCII[(val >> shift) & 0xFULL]);
  }
}
void PutH32(const uint32 val){
  int shift;
  sciSendByte(sciREG1,'0');
  sciSendByte(sciREG1,'x');
  for(shift=32-4;shift>=0;shift-=4) {
    sciSendByte(sciREG1,ASCII[(val >> shift) & 0xFUL]);
  }
}
void PutH16(const uint16 val){
  int shift;
  sciSendByte(sciREG1,'0');
  sciSendByte(sciREG1,'x');
  for(shift=16-4;shift>=0;shift-=4) {
    sciSendByte(sciREG1,ASCII[(val >> shift) & 0xFU]);
  }
}
void PutH8  (const uint8 val){
  int shift;
  sciSendByte(sciREG1,'0');
  sciSendByte(sciREG1,'x');
  for(shift=8-4;shift>=0;shift-=4) {
    sciSendByte(sciREG1,ASCII[(val >> shift) & 0xFU]);
  }
}

void Gets(char *const str) {
  char *ptr;
  ptr = (char *)str;

  while(1) {
    *ptr =(char)sciReceiveByte(sciREG1);
    if(*ptr == ASCII_CR) {break;}
    ptr++;
  }
  *ptr = ASCII_NULL;
}

void DumpB8(uint8 *ptr, int len){
  uint32 i;
  volatile uint8 *ptr8 = (volatile uint8*)ptr;
  for(i=0;i<len;i++) {
    PutH32(i);
    Puts(" : ");
    PutH32((uint32)ptr + i);
    Puts(" : ");
    PutH8(*ptr8);
    ptr8++;
    Puts("\n");
  }
}

void DumpErrors(void)
{
  uint64 status0, status1, status2, status3;

  status0 = esmGetStatus(0, 0xFFFFFFFFFFFFFFFFULL);
  status1 = esmGetStatus(1, 0xFFFFFFFFFFFFFFFFULL);
  status2 = esmGetStatus(2, 0xFFFFFFFFFFFFFFFFULL);
  status3 = esmGetStatus(3, 0xFFFFFFFFFFFFFFFFULL);
  Puts("esmStatus 0 : "); PutH64(status0); Puts("\n");
  Puts("esmStatus 1 : "); PutH64(status1); Puts("\n");
  Puts("esmStatus 2 : "); PutH64(status2); Puts("\n");
  Puts("esmStatus 3 : "); PutH64(status3); Puts("\n");
  ;
}

#define PRNG_A_C                 0xB7D15E25
#define PRNG_C_C                 0x3617C161

/* PRNG(i + 1) = (PRNG_A * PRNG(i) + PRNG_C) Mod 2^32 */
uint32
Prng (volatile uint32 *Seed)
{
  *Seed = (PRNG_A_C * *Seed + PRNG_C_C);

  return *Seed;
}
