//-----------------------------------------------------------------------------
///
/// \brief  "Electronic Assembly" Display
///
///         Controller on EA-Display supports 8- and 4-Bit Mode.
///         We use 4-Bit Mode
///
/// \date   20141217
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//-----------------------------------------------------------------------------


//---Includes------------------------------------------------------------------


//---General--------------------------

#include <string.h>     // memcpy
#include <unistd.h>     // sleep

//---Own------------------------------

#include <biwak/eadisplay.h>
#include <biwak/output.h>
#include <biwak/biwak.h>
#include <biwak/debug.h>         // FREEZE
#include <biwak/platform.h>      // p.
#include <biwak/timer.h>      // delay
#include <lepto/tools.h>


//---Implementation------------------------------------------------------------


#define EADISPLAY_OFFSET_PER_LINE 0x40
/*
int byteDelay=5;     // supposed to be 5us
int enableDelay=1;   // supposed to be 1us
int busyDelay=10;
*/
int byteDelay=0;     // supposed to be 5us
int enableDelay=0;   // supposed to be 1us
int busyDelay=0;



/// \brief  Le contructeur
///
CEaDisplay::CEaDisplay( COutput *_output[4], COutput &_outRs, COutput &_outEnable)
   :outRs(_outRs)
   ,outEnable(_outEnable)
{
   memcpy(output, _output, 4*(sizeof(COutput *)));
   reset();

   char value=0;
   char value2=0;
   char *string=  "Maximilian Seesslen  Maximilian Seesslen  ";
   /*                  "Maximilian Seesslen  Maximilian Seesslen  "
                  "Maximilian Seesslen  Maximilian Seesslen  "
                  "Maximilian Seesslen  Maximilian Seesslen  "
                  "Maximilian Seesslen  Maximilian Seesslen  "
         ;
   */

   if(0)
   {
      char *my="123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.1.2.3.4.5.6.7.8.9.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z";
      putString(my);
      FREEZE;
   }

   if(0)
      while(1)
      {
         writeData(string[value++]);
         if(value>=strlen(string))
         {
            value=value2++;
            if(value2>=strlen(string))
               value2=0;
            //W riteIns(0x01);//clear display
            writeIns(0x02); // Return
            delay(80000);
         }
      };

   if(0)
      while(1)
      {
         uint8_t timeValues[3];
         char data[0x10];
         //writeIns(0x02); // Return
         gotoxy(0,0);
         putString("Clock: ");
         p.rtc[0].getTime(timeValues[0], timeValues[1],timeValues[2]);

         for(int i1=0; i1<3; i1++)
         {
            if(i1)
               putString(":");
            itoa(timeValues[i1], data, sizeof(data), 10, 2);
            putString(data);
         }

         gotoxy(0,1);
         putString("Temp: "
              );

         delay(80000);
      }
}


CEaDisplay::~CEaDisplay()
{

}


void CEaDisplay::reset()
{
   outRs.switchTo(false);
   outEnable.switchTo(false);

   sendNibble(0x03); //Be sure to
   sendNibble(0x03); //be in
   sendNibble(0x03); //8-Bit-Mode
   sendNibble(0x02); //Switch to 4 Bit
   delay(byteDelay); //delay 5us
   writeIns(0x28);//4-Bit-Mode
   writeIns(0x08);//display off
   writeIns(0x06);//entry mode set increment cursor by 1 not shifting display
   writeIns(0x17);//Character mode and internel power on
   writeIns(0x01);//clear display
   writeIns(0x02);//return home
   writeIns(0x0C); //display on
   return;
}


void CEaDisplay::sendNibble (char data)
{
   output[0]->switchTo( (data>>0) & 1);
   output[1]->switchTo( (data>>1) & 1);
   output[2]->switchTo( (data>>2) & 1);
   output[3]->switchTo( (data>>3) & 1);

   outEnable.switchOn();
   delay(enableDelay); //delay 1us (stabilize outupt)
   outEnable.switchOff();
   delay(enableDelay); //delay 1us (stabilize outupt)
}


void CEaDisplay::checkBusy()
{
   delay(busyDelay);
}


void CEaDisplay::writeIns (char data)
{
   CheckBusy();
   outRs.switchTo(false);

   sendNibble( (data&0xF0)>>4);//Highbyte
   sendNibble( data&0x0F ); //Lowbyte
}


void CEaDisplay::writeData (char data)
{
   CheckBusy();
   outRs.switchTo(true);

   sendNibble( (data&0xF0)>>4);//Highbyte
   sendNibble( data&0x0F ); //Lowbyte
}


void CEaDisplay::putString(const char *string)
{
   int i1=0;
   while(string[i1])
   {
      writeData(string[i1++]);
   }
}


void CEaDisplay::putChar(const char ch)
{
   writeData(ch);
}


void CEaDisplay::gotoxy(int x, int y)
{
   writeIns(0x80 | ( (y*EADISPLAY_OFFSET_PER_LINE) + x ) ); // Return
}


//---fin-----------------------------------------------------------------------
