//Arduino_DVM
//Simple Proof of concept to display voltyage using a KTM-S1201
//Written by Jeff Albertson Ver 1.0
//Pin 1  LcdVcc    +5V dc power
//pin 2  LcdVss    0V
//pin 3  LcdnSck   Not Serial clock
//pin 4  LcdSi     Serial data
//pin 5  LcdCnD    Select Command or Data mode
//pin 6  LcdnRes   Reset LCD
//pin 7  LcdnBus   LCD not busy
//pin 8  LcdnCs    LCD not Chip select
//pin 9 Pot wiper  Vlc LCD Contrast
//pin10 NC
// LCD out from Arduino
//#define LcdVcc  29 //+5V dc power
//#define LcdVss  28 // 0V
//#define LcdSck  27 //Not Serial clock
//#define LcdSi  26 //Serial data in
//#define LcdCnD  25 //Command or Not data in
//#define LcdnRes  24 //Not reset low = reset
//#define LcdnBus  23 //Not Busy Only output from LCD
//#define LcdnCs  22 //Not Chip select Low = LCD selected
// LCD across Arduino
#define LcdVcc  22 //+5V dc power
#define LcdVss  23 // 0V
#define LcdSck  24 //Not Serial clock
#define LcdSi   25 //Serial data in
#define LcdCnD  26 //Command or Not data in
#define LcdnRes 27 //Not reset low = reset
#define LcdnBus 28 //Not Busy output from LCD not 
used if delay(1) after LcdnCs changes
#define LcdnCs  29 //Not Chip select Low = LCD selected
//  Put a delay(1) after every LcdnCs change or check LcdnBus
#define t 100
#define t1 10
// The Not Chip select pin is the only unique
// Pin on the LCD all other pins can be paralleled
// for more ktm-s1201 displays

#define adpin 0  //Analog input pin number
#define _Mode 0x40
#define _USync 0x31
#define _FBlink 0x1b
#define _SBlink 0x1a
#define _NoBlink 0x18
#define _DispOn 0x11
#define _Decode 0x15
#define _NoDecode 0x14
#define _LoadPtr 0xE0
#define _SetDp 0xb8   //Set decimal point (Dp)
#define _ClearDp 0x9f //Clear decimal point (Dp)
#define _ClearDsp 0x20 //Clear display memory
// To set Dp you must be in NoDecode mode and point to character (LoadPtr)
//      ---   0x01
//0x10 |   |  0x02
//0x20  ---
//0x40 |   |  0x04
//0x80  --- o 0x08

#define _cet 0x31 //Centigrade
#define _ 0x0     //Space
#define _A  0x77  //
#define _B  0xF4  //
#define _c  0xE0  //
#define _d  0xE6  //
#define _E  0xF1  //
#define _F  0x71  //
#define _G  0xD5  //
#define _H  0x74  //
#define _i  0x04  //
#define _J  0x86  //
#define _K  0x70  //
#define _L  0xD0  //
#define _M  0x76  //
#define _n  0x64  //
#define _o  0xE4  //
#define _P  0x73  //
#define _Q  0xDF  //
#define _r  0x60  //
#define _S  0xB5  //
#define _t  0xF0  //
#define _u  0xC4  //
#define _V  0xD6  //
#define _W  0xF6  //
#define _X  0x56  //
#define _Y  0x72  //
#define _Z  0xEB  //
#define _1  0x06  //
#define _2  0xE3  //
#define _3  0xA7  //
#define _4  0x36  //
#define _5  0xB5  //
#define _6  0xF4  //
#define _7  0x07  //
#define _8  0xF7  //
#define _9  0x37  //
#define _0  0xD7  //


void setup()
{
   pinMode(LcdVcc,OUTPUT);
   pinMode(LcdVss,OUTPUT);
   pinMode(LcdSck,OUTPUT);
   pinMode(LcdSi,OUTPUT);
   pinMode(LcdCnD,OUTPUT);
   pinMode(LcdnRes,OUTPUT);
   pinMode(LcdnBus,INPUT);
   pinMode(LcdnCs,OUTPUT);
   pinMode(13,OUTPUT);

   //Do one time to Initalize KTM-S1201
   digitalWrite(LcdVcc, HIGH); // sets the Power On
   digitalWrite(LcdVss, LOW);
   digitalWrite(LcdCnD, HIGH); //Put in copmmand mode
   digitalWrite(LcdnCs, HIGH); //deselect KTM-S1201
   digitalWrite(LcdSck, HIGH);
   digitalWrite(LcdSi,  HIGH);
   digitalWrite(LcdnRes, LOW); // reset lcd
   delay(10);
   digitalWrite(LcdnRes, HIGH);
   delay(10);
   ktmCommand(_Mode);
   ktmCommand(_USync);
   ktmCommand(_NoBlink);
   ktmCommand(_DispOn);
   ktmCommand(_NoDecode);
   ktmCommand(_ClearDsp);
   //Put initial data on KTM-S1201
   byte TextString[12] = {
     _V,_o,_L,_t,_S,_,_,_0,_0,_0,_d,_c  };
   digitalWrite(LcdCnD, LOW);  	//Put in data mode
   digitalWrite(LcdnCs, LOW);
   delay(1);
   int i;
   for (int i = 11; i >= 0; i --)//Put in KTM-S1201 Right Character First
   {
     ktmshiftOut(TextString[i]);
   }
   digitalWrite(LcdnCs, HIGH); //deselect LCD to display data
   delay(1);                    //always delay after LcdnCs change

}

void loop()
{
   int p = 2;                   //Put Right most L.S.Digit in this location
   int c = 3;                   //Put Decimal point here
   int n = 4;                   //nmber of digits
   int b;
   int vold;
   int  v;

   v = analogRead(adpin);
   //Integer to be displayed
   do
   {
     //scale voltage for 0 - 5v
     //int vs = v * 5 ;
     //int t3 = vs /44;
     //vs = vs -t3 ;
     vs = v * 5 – v * 5 / 44
     ktmPrnNumb(vs,p,c,n); //Dislpay 0.000 to 4.999 vdc
     vold = v;
   }
   while (vold != v );
}

void ktmCommand(byte _cmd)
{
   digitalWrite(LcdCnD, HIGH);
   delay(1);
   digitalWrite(LcdnCs, LOW);
   delay(1);
   ktmshiftOut(_cmd);
   delay(1);
   digitalWrite(LcdnCs, HIGH); //deselect LCD to display data
   delay(1);
}

void ktmshiftOut(byte val)  // same as shiftout command but invert Sck
{
   int i;
   for (i=0;i<8;i++)
   {
     digitalWrite(LcdSi,!!(val & (1<< (7-i))));
     digitalWrite(LcdSck,LOW);
     delay(1);
     digitalWrite(LcdSck,HIGH);
   }
   delay(1);
}

void ktmPrnNumb(int n, byte p,byte d,byte l){
   //n is the number to be printed
   //p is the position for lsb from right starting at 0 and
   //d in the number of digits to the right of the decimal point
   //l is length number of digits in n
   int nt;
   int i;
   int j=1;
   int r=0;

   digitalWrite(LcdCnD, HIGH); //Put in command mode
   digitalWrite(LcdnCs, LOW); //Select LCD
   delay(1);
   ktmshiftOut(_Decode);
   ktmshiftOut(_LoadPtr+p*2);
   digitalWrite(LcdCnD, LOW);  	//Put in data mode
   digitalWrite(LcdnCs, LOW);
   delay(1) ;
   nt = n;
   for (i=0;i<l;i++)//display numbers (reverse order)
   {
     ktmshiftOut(nt%10);
     nt=nt/10;
   }
   j=p*2+d*2;

   if (d>0)  //   Set Decimal point
   {
     digitalWrite(LcdCnD, HIGH); //Put in command mode
     digitalWrite(LcdnCs, LOW); //Select LCD
     delay(1);
     ktmshiftOut(_NoDecode);
     ktmshiftOut(_LoadPtr+j);
     ktmshiftOut(_SetDp);
     delay(1);

   }
   digitalWrite(LcdnCs, HIGH); //deselect LCD to display data
   delay(1);
}