// unit1.cpp v1.0
// Copyright (C)1999-2007 Virtual Integrated Design
// www.rs232pro.com
// This is the main form class.

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
#include <stdio.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
// Create new port.
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
 Port=new RS232Port();
}
//---------------------------------------------------------------------------
// Close port and save settings.
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
 Port->ClosePort();
 delete Port;
 Port=NULL;
 SaveToIni("Dvm-001.ini");
}
//---------------------------------------------------------------------------
// Initialize forms and settings.
void __fastcall TForm1::FormShow(TObject *Sender)
{
 // 1). Initialize Form2 from ini
 // 2). Initialize display from ini
 LoadFromIni("Dvm-001.ini");
 MakeAdjustments();
}
//---------------------------------------------------------------------------
// Update display every 250ms.
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 if( Port->IsOpen() && Form2->AutoCheckBox->Checked )
 { DisplayAdcValue(); }
}
//---------------------------------------------------------------------------
// Clicking the "Advanced" menu item shows the form 2 menu that allows the user
// to set the samples, settle time, input selection, input compensation, auto-
// update and com port.
// When the user clicks "OK" we return to this method and we must adjust the
// settings appropriately.
void __fastcall TForm1::Advanced1Click(TObject *Sender)
{
 int ReturnCode=Form2->ShowModal();
 if(ReturnCode==mrOk)
 {
  MakeAdjustments();
 }
}
//---------------------------------------------------------------------------
// We must "Make Adjustments" to our settings after the ini file is loaded
// and whenever we return from the advanced form.
void TForm1::MakeAdjustments(void)
{
 AnsiString s="";
 if(Form2->AutoCheckBox->Checked){ Timer1->Enabled = true; }
 else{ Timer1->Enabled = false; }
 DisplayRange();
 if(Port->IsOpen())
 {
  SetAdcSamples((unsigned char)Form2->SamplesEdit->Text.ToInt());
  SetAdcSettleTime((unsigned char)Form2->SettleEdit->Text.ToInt());
  DisplayAdcValue();
 }
}
//---------------------------------------------------------------------------
// Clicking the "Refresh" menu item displays 1 reading at a time.
void __fastcall TForm1::Refresh1Click(TObject *Sender)
{
 AnsiString s="";
 if(Port->IsOpen()){ DisplayAdcValue(); }
 else
 {
  s = "Port must be open first.";
  Application->MessageBox(s.c_str(),"Error",MB_OK | MB_ICONWARNING);
 }
 DisplayRange();
}
//---------------------------------------------------------------------------
// The open button shows "Open Port" when the port is closed and "Close Port"
// when its open. When the port can't be opened a warning message is shown.
void __fastcall TForm1::OpenButtonClick(TObject *Sender)
{
 AnsiString s = Form2->PortCombo->Text;
 AnsiString str = "";
 if(OpenButton->Caption=="Open Port")
 {
  bool ok = Port->OpenPort(s);
  if(!ok)
  {
   str = "Can't open port.";
   Application->MessageBox(str.c_str(),"Error",MB_OK | MB_ICONWARNING);
  }
  if(Port->IsOpen()){ OpenButton->Caption="Close Port"; }
 }
 else
 {
  Port->ClosePort();
  if(!Port->IsOpen()){ OpenButton->Caption="Open Port"; }
 }
}
//---------------------------------------------------------------------------
// This method gets the reading from the micro, calculates the result based
// on what resistors are present for a given input and displays that value
// on the main readout label. value = R2/R1+R2.
bool TForm1::DisplayAdcValue(void)
{
 unsigned short value = 1;
 double divisor = 100000; // R2 = 100K
 double result = 0;
 char display[]={"0000000"};
 double volts_per_count = 5;
 volts_per_count /= 1024;
 bool ok = GetAdcValue(value);
 if( ok && (value<=1024) ){ result = (value * volts_per_count); }
 if(ok && Form2->HvRadioButton->Checked) // R2/R1+R2
 {
  divisor /= 1100000;
  result /= divisor;
  result += Form2->HvEdit->Text.ToDouble();
  sprintf(display,"%2.2f",result);
 }
 else if(ok && Form2->MvRadioButton->Checked) // R2/R1+R2
 {
  divisor /= 599000;
  result /= divisor;
  result += Form2->MvEdit->Text.ToDouble();
  sprintf(display,"%2.2f",result);
 }
 else if(ok && Form2->LvRadioButton->Checked)
 {
  result += Form2->LvEdit->Text.ToDouble(); // Add comp if any
  sprintf(display,"%1.3f",result);
 }
 if(ok)
 {
  strcat(display,"v");
  MainReadOut->Caption = display;
 }
 return ok;
}
//---------------------------------------------------------------------------
// This method shows the input range selection on the smaller display label.
void TForm1::DisplayRange(void)
{
 if(Form2->HvRadioButton->Checked){ SelectReadOut->Caption="H"; }
 else if(Form2->MvRadioButton->Checked){ SelectReadOut->Caption="M"; }
 else if(Form2->LvRadioButton->Checked){ SelectReadOut->Caption="L"; }
}
//---------------------------------------------------------------------------
// The micro returns a 2 byte representation of the 10-bit value that is seen
// by the micro's adc. The high byte is transmitted first. The amount of settle
// time after the command is received and the number of averaged samples taken
// for the adc reading are determined by the variables in the micro. These var-
// iables are defaulted to 16 samples and 50ms settle time and can be set by
// calling the SetAdcSamples and SetAdcSettleTime methods.
bool TForm1::GetAdcValue(unsigned short &us)
{
 bool ok=false;
 unsigned char uc[]={0,0};
 unsigned char* ucp = (unsigned char*)&us;
 Port->PutByte(0x01);
 Port->PutByte(0x04);
 if( Port->GetByte(uc[0]) && Port->GetByte(uc[1]) )
 {
  ok = true;
  *(ucp+1) = uc[0];
  *ucp = uc[1];
 }
 return ok;
}
//---------------------------------------------------------------------------
// Sets the number of samples variable in the micro. The variable is used
// by the micro to determine how many samples to take and average when a
// GetAdcValue is requested by the pc.
bool TForm1::SetAdcSamples(unsigned char uc) // loops per data request
{
 bool ok=false;
 unsigned char temp_uc = 0;
 Port->PutByte(0x01);
 Port->PutByte(0x02);
 Port->PutByte(uc);
 if( Port->GetByte(temp_uc) )
 {
  if( temp_uc == uc ){ ok = true; }
 }
 return ok;
}
//---------------------------------------------------------------------------
// Sets the settle time variable which determines how long the delay is from
// the time the request is received until the micro starts taking data.
// We have a delay after receiving the byte to let the supply settle. The act
// of receiving a byte pulls on the supply and may affect the accuracy of the
// reading because the micro gets its reference from the supply voltage.
bool TForm1::SetAdcSettleTime(unsigned char uc) // Milliseconds
{
 bool ok=false;
 unsigned char temp_uc = 0;
 Port->PutByte(0x01);
 Port->PutByte(0x03);
 Port->PutByte(uc);
 if( Port->GetByte(temp_uc) )
 {
  if( temp_uc == uc ){ ok = true; }
 }
 return ok;
}
//---------------------------------------------------------------------------
// Initializes new Form2 values.
bool TForm1::LoadFromIni(char* name)
{
 bool ok=false;
 if( FileExists(name) ) // Check for file exist
 {
  TStringList* inip=new TStringList;
  inip->LoadFromFile(name);
  if(inip->Count > 15)
  {
   ok = true;
   Form2->PortCombo->ItemIndex = inip->Strings[1].ToInt();
   if(inip->Strings[3] == "55V"){ Form2->HvRadioButton->Checked = true; }
   else if(inip->Strings[3] == "29V"){ Form2->MvRadioButton->Checked = true; }
   else if(inip->Strings[3] == "5V"){ Form2->LvRadioButton->Checked = true; }
   else{ Form2->HvRadioButton->Checked = true; }
   Form2->HvEdit->Text = inip->Strings[5];
   Form2->MvEdit->Text = inip->Strings[7];
   Form2->LvEdit->Text = inip->Strings[9];
   if(inip->Strings[11] == "true"){ Form2->AutoCheckBox->Checked = true; }
   else{ Form2->AutoCheckBox->Checked = false; }
   Form2->SamplesEdit->Text = inip->Strings[13];
   Form2->SettleEdit->Text = inip->Strings[15];
  }
  if(inip){ delete inip; }
 }
 return ok;
}
//---------------------------------------------------------------------------
// Saves Form2 parameters to ini file.
bool TForm1::SaveToIni(char* name)
{
 // Load ini and save size parameters
 bool ok=false;
 if( FileExists(name) ) // Check for file exist
 {
  TStringList* inip=new TStringList;
  inip->LoadFromFile(name);
  inip->Strings[1] = Form2->PortCombo->ItemIndex;
  if(Form2->LvRadioButton->Checked){ inip->Strings[3] = "5V"; }
  if(Form2->MvRadioButton->Checked){ inip->Strings[3] = "29V"; }
  if(Form2->HvRadioButton->Checked){ inip->Strings[3] = "55V"; }
  inip->Strings[5] = Form2->HvEdit->Text;
  inip->Strings[7] = Form2->MvEdit->Text;
  inip->Strings[9] = Form2->LvEdit->Text;
  if(Form2->AutoCheckBox->Checked){ inip->Strings[11] = "true"; }
  else{ inip->Strings[11] = "false"; }
  inip->Strings[13] = Form2->SamplesEdit->Text;
  inip->Strings[15] = Form2->SettleEdit->Text;
  inip->SaveToFile(name);
  delete inip;
 }
 return ok;
}
//---------------------------------------------------------------------------