/******************************************************************************
 * envDriver.c
 ******************************************************************************
 * Driver routines for the Environmental Fan Card Board
 *
 * Created - 03/20/2002
 *
 * Version	Date		Intls	Comments
 * -------	----------	-----	---------------------------------------
 * 1.00.00	07/06/2002	gatjr	initial release
 *
 ******************************************************************************
 *
 * f=envOpen(address)			- Open board for access, set address
 * f=envSetup()				- Initialize board
 *
 * b=envDiagLED(state)			- Read and set Diagnostic LED state
 *
 * i=envReadCfg()			- Read configuration jumpers
 * i=envReadDig()			- Read digital inputs
 * i=envReadAna(channel)		- Read analog voltage
 *
 * mthr3InitTemp()					- Initialize temp. sys
 * mthr3ReadTemp(*TempNow,*TempHi,*TempLo,*TempCfg)	- Read temp. values
 * mthr3WriteTemp (TempHi,TempLo)			- Set temp. limits
 *
 ******************************************************************************
 * Built with Greenhills Compiler Multi V3.5
 * (C) Copyright 2002 parvus Corporation.  All rights reserved.
 ******************************************************************************/


#include "pc104_555.h"
#include "envDriver.h"
#include "parvLibrary.h"
#include "serial.h"

////////////////////////////////////////////////////////////////////////////////
// Definitions and Globals

#define DEFDECDIGITS 6

static int TempDDRBit, TempCLKBit, TempDTIBit, TempDTOBit, TempPort, TempWindow;              // 0 - Not Used
static int TempBank, TempShadow, TempType, TempResetBit, TempResetBit1; 

int envIOBase;		// Base address of Board

// Local function headers
static void TempCommand(int cmd);
static int TempInput( int Cmd);
static void TempOutput (int Cmd, int Dta);
static void TempReset(int ch);
static void TempDisable(int ch);
static void TempEnable(int ch);
static void TempBusIOWrite8(long TP, int TS);

////////////////////////////////////////////////////////////////////////////////
// Environmental Fan Card Board Functions
////////////////////////////////////////////////////////////////////////////////

// Open access to board
int envOpen(int address){

    int err;

    envIOBase = address;		// Set base address
    err = envSetup();			// Setup board
    
    return(err);
}

// Perform required initial setup of board
int envSetup(void) {
    int err;

    envInitTemp(0);			// Start temperature sensor 0
    envInitTemp(1);			// Start temperature sensor 1

    err=0;
    
    return(err);
}

// Access diagnostic LED of board
int envDiagLED(int state) {

    int f;
    f = BusIORead8(envIOBase+1);
    if (state==0) BusIOWrite8(envIOBase+1, f | 0x02);	// LED Off
    else if (state==1) BusIOWrite8(envIOBase+1,f & 0xFD);	// LED On

    if ((BusIORead8(envIOBase+1) & 0x02)==0) f = 1; else f = 0;			// LED state

    return(f);
}


////////////////////////////////////////////////////////////////////////////////

// Read Configuration jumpers
int envReadCfg(void){
    int b;
    b = BusIORead8(envIOBase+5);
    return(b);
}

// Read digital Inputs
int envReadDig(void){
    int b;
    b = BusIORead8(envIOBase+3);
    return(b);
}

// Read Humidity Inputs
int envReadHum(void){
    int b;
    b = BusIORead8(envIOBase+0);
    return(b);
}
// Write Humidity Inputs
void envWriteHum(int val){
    BusIOWrite8(envIOBase+0, val);
    return;
}

// Write to digital outputs
int envSetDig(int val){
    int r;
    r = BusIORead8(envIOBase+1);
    if (val!=-1) BusIOWrite8(envIOBase+1,(r & 0x0F) | ((val & 0x0F)<<4));
    //r = (((BusIORead8(envIOBase+1) & 0xF0)>>4) & 0x0F);
    r = BusIORead8(envIOBase+1);
    return(r);
}

// Write to enables
int envSetEnables(int val){
    int r;
    r = BusIORead8(envIOBase+6);
    if (val!=-1) BusIOWrite8(envIOBase+6,(r & 0x1F) | ((val & 0x07)<<5));
    r = (((BusIORead8(envIOBase+6) & 0xE0)>>5) & 0x07);
    return(r);
}

// Turn Fan On/Off
int envFan(int val){
    int r;
    r = BusIORead8(envIOBase+1);
    if (val==1) BusIOWrite8(envIOBase+1,r | 0x04);
    else if (val==0) BusIOWrite8(envIOBase+1,r & (~0x04));

    r = BusIORead8(envIOBase+1) & (0x04);
    if (r!=0) r=1;
    return(r);
}


// Read environmental analog channels
int envReadAna(int channel){
    int dta;
    BusIOWrite8(envIOBase+8,(channel & 0x07) + 0x80);		// Start conversion
    pdelay(10);
    dta = BusIORead8(envIOBase+8);
    return(dta);                                // Return Data

}

// Initialize environmental board temperaure sensor
void envInitTemp(int ch) {

    int TempNow, TempHi, TempLo, TempCfg;

    TempDDRBit = 0x2;            // Setup Temperature I/O
    TempCLKBit = 0x4;
    TempDTIBit = 0x1;
    TempDTOBit = 0x1;
    TempResetBit = 0x8;
    TempResetBit1 = 0x10;
    TempPort = envIOBase + 6;
    TempWindow = 0;              // 0 - Not Used
    TempBank = 1;
    TempShadow = 0;
    TempType = 0;                // 0=F, 1=C
    if (TempWindow > 0) BusIOWrite8(TempWindow, TempBank);     // Set access window
    TempShadow = (TempPort);	// load shadow
    TempEnable(ch);
    TempReset(ch);
    TempCommand (0xC);               // Send Temperature command
    TempCommand (0x2);               // Continuous Conversion
    TempReset(ch);
    TempCommand (0xEE);              // Start continuous Conversion
    TempReset(ch);
    TempDisable(ch);

    envReadTemp (&TempNow, &TempHi, &TempLo, &TempCfg, ch);
}

// Set environmental board thermostat limits
void envWriteTemp (int TempHi, int TempLo, int ch) {
    TempEnable(ch);
    sdelay();
    TempShadow = BusIORead8(TempPort);	// load shadow
    TempReset(ch);
    TempCommand (0xC);               	// Send Temperature command
    TempCommand(2);               	// Continuous Conversion
    TempReset(ch);
    TempOutput(0x2, TempLo);         	// Send TL command
    TempReset(ch);
    TempOutput(0x1, TempHi);         	// Send TH command
    TempReset(ch);
    TempCommand(0xEE);              	// Start continuous Conversion
    TempReset(ch);
    sdelay();
    TempDisable(ch);
}
// Read environmental board temperature sensor
void envReadTemp(int *TempNow, int *TempHi, int *TempLo, int *TempCfg, int ch) {
    TempEnable(ch);
    sdelay();
    TempShadow = BusIORead8(TempPort);	// load shadow
    TempReset(ch);
    *TempLo = TempInput(0xA2);       // Read Low temp set point
    TempReset(ch);
    *TempHi = TempInput(0xA1);       // Read High temp set point
    TempReset(ch);
    *TempNow = TempInput(0xAA);      // Read current temperature
    TempReset(ch);
    *TempCfg = TempInput(0xAC);      // Read current configuration
    TempReset(ch);
    sdelay();
    TempDisable(ch);
}


//////////////////////////////////////////////////////////////////////////////////////////////////
// Local Support Functions
//////////////////////////////////////////////////////////////////////////////////////////////////
static void TempBusIOWrite8(long TP, int TS) {
    BusIOWrite8(TP, (BusIORead8(TempPort) & 0xE0) | (TS & 0x1F));
}

static void TempCommand(int cmd){
    int i;
    
    if (TempWindow > 0) TempBusIOWrite8(TempWindow, TempBank);       // Set access window

    TempShadow = TempShadow | TempDDRBit;            		// Set As Output
    TempBusIOWrite8(TempPort, TempShadow);

    for (i=0; i<8; i++) {                                  	// LSB First
	if (((cmd >> i) & 0x01) == 0) TempShadow = TempShadow & (~TempDTOBit); // Lower Data
	else TempShadow = TempShadow | TempDTOBit;            			 // Raise Data

	TempBusIOWrite8(TempPort, TempShadow);                    	// Set data

	TempShadow = TempShadow & (~TempCLKBit);         	// Lower Clock
	TempBusIOWrite8(TempPort, TempShadow);

	TempShadow = TempShadow | TempCLKBit;                	// Raise Clock
	TempBusIOWrite8(TempPort, TempShadow);
    }

}
static int TempInput( int Cmd){
    int Dta, Bit, i;
    
    TempCommand (Cmd);

    TempShadow = TempShadow & (~TempDDRBit);         // Set As Input
    TempBusIOWrite8(TempPort, TempShadow);

    Dta = 0;
    for (i=0;i<9;i++) {
 	TempShadow = TempShadow & (~TempCLKBit);        // Lower Clock
	TempBusIOWrite8(TempPort, TempShadow);
	Bit = BusIORead8(TempPort) & TempDTIBit;
	Dta = Dta >> 1;
	if (Bit > 0) Dta = Dta + 0x100;
	TempShadow = TempShadow | TempCLKBit;                // Raise Clock
	TempBusIOWrite8(TempPort, TempShadow);
    }
    return(Dta);			// Return Temperature
}

static void TempOutput (int Cmd, int Dta) {
    int i;
    
    TempCommand (Cmd);

    TempShadow = TempShadow | TempDDRBit;            	// Set As Output
    TempBusIOWrite8(TempPort, TempShadow);

    for (i=0;i<9;i++) {	                             	// LSB First
	if (((Dta >> i) & 0x01) == 0) TempShadow = TempShadow &  (~ TempDTOBit); // Lower Data
	else TempShadow = TempShadow | TempDTOBit;            			 // Raise Data
	TempBusIOWrite8(TempPort, TempShadow);	      	// Set data
	TempShadow = TempShadow & (~TempCLKBit);     	// Lower Clock
	TempBusIOWrite8(TempPort, TempShadow);
	TempShadow = TempShadow | TempCLKBit;         	// Raise Clock
	TempBusIOWrite8(TempPort, TempShadow);
    }
}

static void TempReset(int ch){

    if (ch==0) {
	TempShadow = TempShadow & (~TempResetBit);		// Lower Reset
	TempBusIOWrite8(TempPort, TempShadow);
	sdelay();
	TempShadow = TempShadow | TempResetBit;
	TempBusIOWrite8(TempPort, TempShadow);			// Raise Reset
    }
    else {
	TempShadow = TempShadow & (~TempResetBit1);		// Lower Reset
	TempBusIOWrite8(TempPort, TempShadow);
	sdelay();
	TempShadow = TempShadow | TempResetBit1;
	TempBusIOWrite8(TempPort, TempShadow);			// Raise Reset
    }

}

static void TempDisable(int ch){

    if (ch==0) {
	TempShadow = TempShadow & (~TempResetBit);		// Lower Reset
	TempBusIOWrite8(TempPort, TempShadow);
    }
    else {
	TempShadow = TempShadow & (~TempResetBit1);		// Lower Reset
	TempBusIOWrite8(TempPort, TempShadow);
    }

}

static void TempEnable(int ch){

    if (ch==0) {
	TempShadow = TempShadow | TempResetBit;
	TempBusIOWrite8(TempPort, TempShadow);			// Raise Reset
    }
    else {
	TempShadow = TempShadow | TempResetBit1;
	TempBusIOWrite8(TempPort, TempShadow);			// Raise Reset
    }

}

