// HmitrApi.cpp : Defines the exported functions for the DLL application.
//
/*
 * \brief Library functions for accessing HMI controller registers
 *
 * Automated backlight control, depending on the ambient
 * light, follows the following diagram
 *
 * mab 
 *    ^
 *    |
 *    |
 * dbl| . . . . . . .   ---------------
 *    |               / .
 *    |              /  .
 *    |             /   .
 *    |            /    .
 *    |           /     .
 * nbl|----------       .
 *    |          .      .
 *    |          .      .
 *    +----------------------------------->
 * mib          nt       dt              ambient light

 mab: Maximum backlight level, 0xff constant
 mib: Minimum backlight level, 0 constant

 * This algorithm can be configured by programming the
 * following 4 parameters:
 * dbl Day backlight value 
 * nbl Night backlight value 
 * nt  Night threshold of Ambient light 
 * dt  Day threshold of Ambient light 
 *
 	The following conditions must be met:
	dt >= nt
	mib <= nbl <= dbl <= mab

 * The HMI controller is attached to the system via a USB-to-serial
 * converter. This is the library, which handles the low-level
 * serial protocols.
 *
*/

#include "stdafx.h"
#include "HmitrApi.h"
#include "HmitrRegAccess.h"
#include "hmiregaccess_defs.h"
#include "hmiregistermap.h"

typedef unsigned char u8;

int mab = 0xff;
int mib = 0;


/*
int GetCOMport(LPCWSTR ComPort)
{
TCHAR szValue[128];
 
DWORD dwLen=sizeof(szValue);
 
DWORD Status; 
 

	DWORD   dwRegValueType   = REG_SZ;
	LPCWSTR lpRegSubKey      = TEXT("SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS\\VID_403+PID_6010+7&a638430&0&3&1\\0000\\Device Parameters");
	LPCWSTR lpRegValueName   = TEXT("\\PortName");


 
     Status = RegGetValueW(HKEY_LOCAL_MACHINE, 
                            // TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
                             //TEXT("\\Device\\Serial2"),
							 TEXT("SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS\\VID_403+PID_6010+7&a638430&0&3&1\\0000\\Device Parameters"),
							 TEXT("\\PortName"),
                             RRF_RT_REG_SZ,
                             NULL,szValue,&dwLen);
 
	if(ERROR_SUCCESS==Status)
	{
	 
			  ComPort = szValue;
	 
	}
	else
		return -1;

		

	return 0;

}
*/
/**
* \brief Open HMI API
*
* \param fname file name of serial device
* \param baud Baud rate
* \return file descriptor of serial device \n
*		Error number, see hmi_errstring() \n
*
*/
HMITRAPI_API int hmiapi_open(LPCWSTR ComPort)
{
//	if (GetCOMport(ComPort) < 0)
//		return -1;

	
	ComPort = L"COM7";
	return fnHmitrRegAccess_init_port(ComPort);
}
/**
* \brief Close HMI API
*
* \param none
*
*/
HMITRAPI_API void hmiapi_close(void)
{
	fnHmitrRegAccess_close_port();
}

/**
* \brief Read Ambient light value
*
* \param fd serial device file descriptor
* \param pretval pointer to readback value
* \param which \n
*     0 .. current ambient light value \n
*     1 .. night ambient light value \n
*     2 .. day ambient light value \n
*
* \return 0 on Success \n
*	Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_amblight_read(int which, int *pretval)
{

	switch(which)
	{
		case 0: return fnHmiRegRead( HMIREG_R_AMBLIGHT, pretval);
		case 1: return fnHmiRegRead( HMIREG_RW_AMBLIGHT_NIGHTVAL, pretval);
		case 2: return fnHmiRegRead( HMIREG_RW_AMBLIGHT_DAYVAL, pretval);
		default: break;
	}
	return HMIERR_EINVAL;

}
/**
* \brief Write Ambient light value
*
* \param value value to write
* \param which \n
*     1 .. night ambient light value \n
*     2 .. day ambient light value \n
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_amblight_write(int which, unsigned char value)
{
	int val, *pretval;
	pretval = &val;

	//check for out of bounds
	if (value > mab)
		value = mab;
	else if(value < mib)
		value = mib;

	switch(which)
	{
		case 2: 
			fnHmiRegRead( HMIREG_RW_AMBLIGHT_DAYVAL, pretval);
		
				if (*pretval >= value) //ok:  dt >= requested nt value
					return fnHmiRegWrite( HMIREG_RW_AMBLIGHT_NIGHTVAL, value); //nt
				else // not ok: set nt = dt to meet legal conditions
					return fnHmiRegWrite( HMIREG_RW_AMBLIGHT_NIGHTVAL, val);
		

		case 1: 
			fnHmiRegRead( HMIREG_RW_AMBLIGHT_NIGHTVAL, pretval);
			
				if (*pretval <= value) //ok: nt <= requested dt value			
					return fnHmiRegWrite( HMIREG_RW_AMBLIGHT_DAYVAL, value);   //dt
				else  // not ok:  set dt = nt to meet legal conditions
					return fnHmiRegWrite( HMIREG_RW_AMBLIGHT_DAYVAL, val);
			
		default: break;
	}
	return HMIERR_EINVAL;	
}
/**
* \brief Read Backlight value
*
* \param pretval pointer to readback value
* \param which \n
*     0 .. current backlight value \n
*     1 .. night backlight value \n
*     2 .. day backlight value \n
*
* \return 0 on Success \n
*	Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_backlight_read(int which, int *pretval)
{
	switch(which)
	{
		case 0: return fnHmiRegRead( HMIREG_R_BLCURR, pretval);
		case 1: return fnHmiRegRead( HMIREG_RW_BLNIGHT, pretval);
		case 2: return fnHmiRegRead( HMIREG_RW_BLDAY, pretval);
		default: break;
	}
	return HMIERR_EINVAL;
}
/**
* \brief Write Backlight value
*
* \param value value to write
* \param which \n
*     1 .. night backlight value \n
*     2 .. day backlight value \n
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_backlight_write(int which, unsigned char value)
{

	int val, *pretval;
	pretval = &val;


	//check for out of bounds
	if (value > mab)
		value = mab;
	else if(value < mib)
		value = mib;

	switch(which)
	{
	    case 1: 
				fnHmiRegRead( HMIREG_RW_BLDAY, pretval);

				if (*pretval >= value)//ok:  dbl >= requested nbl value
					return fnHmiRegWrite( HMIREG_RW_BLNIGHT, value);	//nbl
				else // not ok:  set nbl = dbl to meet legal conditions
				    return fnHmiRegWrite( HMIREG_RW_BLNIGHT, val);


		case 2: 
				fnHmiRegRead( HMIREG_RW_BLNIGHT, pretval);
			
				if (*pretval <= value)//ok:  nbl <= requested dbl value
					return fnHmiRegWrite( HMIREG_RW_BLDAY, value);		 //dbl
				else // not ok:  set nbl = dbl to meet legal conditions
					return fnHmiRegWrite( HMIREG_RW_BLDAY, val);


		default: break;
	}
	return HMIERR_EINVAL;
}
/**
* \brief Read Ambient temperature
*
* \param pretval pointer to readback value
*
* \return 0 on Success \n
*	Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_ambtemp_read(int *pretval)
{
	return fnHmiRegRead( HMIREG_R_AMBTEMP, pretval);
}
/**
* \brief Configure Backlight on/off Power-on-default
*
* Configures, wether the Backlight is on or off at Power-On
* \param value Default value 0=off, 1=on
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_blonoff_default_write(unsigned char value)
{
	return fnHmiRegWrite( HMIREG_RW_BLONOFF,value | BLONOFF_PERMMSK);

}
/**
* \brief Read Backlight on/off status
*
* \param pretval pointer to readback value
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_blonoff_read(int *pretval)
{
	return fnHmiRegRead( HMIREG_RW_BLONOFF, pretval);

}
/**
* \brief Write Backlight on/off
*
* \param value value to write 0=off, 1=on
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_blonoff_write(unsigned char value)
{
	return fnHmiRegWrite( HMIREG_RW_BLONOFF,value);

}


/**
* \brief decrease backlight level
*
* \param dec_step  decrement value
*
* \return 0 on Success \n
* 	Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_dec_brightness(int dec_step)
{
        u8 amb, dt, nt;    // current ambient and ambient threshold values
        u8 bl, nbl, dbl;   // current backlight and backlight night/day limits
        u8 nt_lim, dt_lim; // ambient light limits (1/3=night, 2/3=inbetween, 3/3=day)
        u8 range;
        int pretval, rc;


	/* we want a meaningful value for the decrement step */
	if (dec_step < 0 || dec_step > 0xff)
		return HMIERR_PARAM;

        // getting current ambient light value 
        rc = hmi_amblight_read( 0, &pretval);
        if (rc == 0)
                amb = (u8) pretval;
        else
                return HMIERR_GETAMB;

        // getting night ambient value (nt)
        rc = hmi_amblight_read( 1, &pretval);
        if (rc == 0)
                nt = (u8) pretval;
        else
                return HMIERR_GETAMB;

        // getting day ambient value (dt)       
        rc = hmi_amblight_read( 2, &pretval);
        if (rc == 0)
                dt = (u8) pretval;
        else
                return HMIERR_GETAMB;

        // getting current backlight level
        rc = hmi_backlight_read( 0, &pretval);
        if (rc == 0)
                bl = (u8) pretval;
        else
                return HMIERR_GETBACKL;

        // getting current night backlight level
        rc = hmi_backlight_read( 1, &pretval);
        if (rc == 0)
                nbl = (u8) pretval;
        else
                return HMIERR_GETBACKL;

        // getting current day backlight level
        rc = hmi_backlight_read( 2, &pretval);
        if (rc == 0)
                dbl = (u8) pretval;
        else
                return HMIERR_GETBACKL;

	/* calculate the ambient range and divide it into 3 parts */
        range = dt - nt;
        nt_lim = (range / 3) + nt;
        dt_lim = (range / 3) + nt_lim + nt;

//      DBG(("*** amb=%02x, dt=%02x, nt=%02x, bl=%02x, nbl=%02x, dbl=%02x,  range=%d, nt_lim=%d, dt_lim=%d\n",
 //                        (u8)amb, (u8)dt, (u8)nt, (u8)bl, (u8)nbl, (u8)dbl, (u8)range, (u8)nt_lim, (u8)dt_lim));

        if (amb <= nt_lim) {
		/* border checks and calculating the new nbl value, should avoid turnarounds */
		if (nbl >= dec_step)
			nbl-=dec_step;
		else 
			nbl=0x0;

		if (dbl < nbl) /* forbidden, and theoretically not possible to achieve (?) */
			return HMIERR_BLRANGE;

                hmi_backlight_write( 1, nbl);
        } else if (amb > nt_lim && amb <= dt_lim) {
		/* border checks and calculating the new nbl and dbl value, should avoid turnarounds */
		if (nbl >= dec_step)
			nbl-=dec_step;
		else
			nbl=0x0;

		if (dbl >= dec_step)
			dbl-=dec_step;
		else
			dbl=0x0;
        
		if (dbl < nbl) /* forbidden, and theoretically not possible to achieve (?) */
			return HMIERR_BLRANGE;

                // incrementing both nbl and dbl
//               DBG(("setting backlight: NIGHT nbl=0x%02x AND DAY dbl=0x%02x\n", nbl, dbl));
                hmi_backlight_write( 1, nbl);
                hmi_backlight_write( 2, dbl);
        } else {
		/* border checks and calculating the new dbl value, should avoid turnarounds */
		if (dbl >= dec_step)
			dbl-=dec_step;
		else
			dbl=0x0;
        
		if (dbl < nbl) /* forbidden, and theoretically not possible to achieve (?) */
			return HMIERR_BLRANGE;

                // this should appeal to dtl < curr_amb < dt
   //             DBG(("setting backlight: DAY dbl=0x%02x\n", dbl));
                hmi_backlight_write( 2, dbl);
        }

        return 0;
}

/**
* \brief increase backlight level
*
* \param inc_step  increment value
*
* \return 0 on Success \n
* 	Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_inc_brightness(int inc_step)
{
	u8 amb, dt, nt;    // current ambient and ambient threshold values
	u8 bl, nbl, dbl;   // current backlight and backlight night/day limits
	u8 nt_lim, dt_lim; // ambient light limits (1/3=night, 2/3=inbetween, 3/3=day)
	u8 range;
	int pretval, rc;


	/* we want a meaningful value for the increment step */
	if (inc_step < 0 || inc_step > 0xff)
		return HMIERR_PARAM;

	// getting current ambient light value 
	rc = hmi_amblight_read( 0, &pretval);
	if (rc == 0)
		amb = (u8) pretval;
	else
		return HMIERR_GETAMB;

	// getting night ambient value (nt)
	rc = hmi_amblight_read( 1, &pretval);
	if (rc == 0)
		nt = (u8) pretval;
	else
		return HMIERR_GETAMB;

	// getting day ambient value (dt)	
	rc = hmi_amblight_read( 2, &pretval);
	if (rc == 0)
		dt = (u8) pretval;
	else
		return HMIERR_GETAMB;

	// getting current backlight level
	rc = hmi_backlight_read( 0, &pretval);
	if (rc == 0)
		bl = (u8) pretval;
	else
		return HMIERR_GETBACKL;

	// getting current night backlight level
	rc = hmi_backlight_read( 1, &pretval);
	if (rc == 0)
		nbl = (u8) pretval;
	else
		return HMIERR_GETBACKL;

	// getting current day backlight level
	rc = hmi_backlight_read( 2, &pretval);
	if (rc == 0)
		dbl = (u8) pretval;
	else
		return HMIERR_GETBACKL;

	/* calculate the ambient range and divide it into 3 parts */
	range = dt - nt;
	nt_lim = (range / 3) + nt;
	dt_lim = (range / 3) + nt_lim + nt;

//	DBG(("*** amb=%02x, dt=%02x, nt=%02x, bl=%02x, nbl=%02x, dbl=%02x,  range=%d, nt_lim=%d, dt_lim=%d\n", 
//			(u8)amb, (u8)dt, (u8)nt, (u8)bl, (u8)nbl, (u8)dbl, (u8)range, (u8)nt_lim, (u8)dt_lim));

	if (amb <= nt_lim) {
		/* border checks and calculating the new nbl value, should avoid turnarounds */
		if (nbl <= 0xff - inc_step)
			nbl+=inc_step;
		else
			nbl=0xff;

		/* Firmware would not allow this */
		if (dbl < nbl)
			return HMIERR_BLRANGE;

		// setting night backlight level
//		DBG(("setting backlight: NIGHT nbl=0x%02x\n", nbl));
		hmi_backlight_write( 1, nbl);
	} else if (amb > nt_lim && amb <= dt_lim) {
		/* border checks and calculating the new nbl and dbl value, should avoid turnarounds */
		if (nbl <= 0xff - inc_step)
			nbl+=inc_step;
		else
			nbl=0xff;

		if (dbl <= 0xff - inc_step)
			dbl+=inc_step;
		else
			dbl=0xff;

		/* Firmware would not allow this */
		if (dbl < nbl)
			return HMIERR_BLRANGE;

		// incrementing both nbl and dbl
//		DBG(("setting backlight: NIGHT nbl=0x%02x AND DAY dbl=0x%02x\n", nbl, dbl));
		hmi_backlight_write( 1, nbl);
		hmi_backlight_write( 2, dbl);
	} else { // this should appeal to dtl < curr_amb < dt
		/* border checks and calculating the new nbl and dbl value, should avoid turnarounds */
		if (dbl <= 0xff - inc_step)
			dbl+=inc_step;
		else
			dbl=0xff;

		/* Firmware would not allow this */
		if (dbl < nbl)
			return HMIERR_BLRANGE;

//		DBG(("setting backlight: DAY dbl=0x%02x\n", dbl));
		hmi_backlight_write( 2, dbl);
	}

	return 0;

}

//================ LED ================================================
/**
* \brief Read LED status
*
* \param ledno LED number (0..3)
* \param pretval pointer to readback value
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_led_read(unsigned char ledno, int *pretval)
{
	if (ledno >= NUM_OF_LEDS) return HMIERR_EINVAL;
	return fnHmiRegRead( HMIREG_RW_LED1+ledno, pretval);

}
/**
* \brief Write to LED
*
* \param ledno LED number (0..3)
* \param ledmode ledmode to write
*			0 = off \n
*			1 = steady on \n
*			2 = blink slowly \n
*			3 = blink fast \n
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_led_write(unsigned char ledno, unsigned char ledmode)
{
	if (ledno >= NUM_OF_LEDS) return HMIERR_EINVAL;
	if (ledmode > 3) return HMIERR_EINVAL;
	return (fnHmiRegWrite( HMIREG_RW_LED1+ledno,ledmode));

}

//================ watchdog ================================================
/**
* \brief Write Watchdog interval
*
* \param value Interval value in ms, 0 disables Watchdog
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_wdtim_write( unsigned short value)
{
	return fnHmiRegWrite(HMIREG_RW_WDTIM_HIGH, (unsigned char)(value>>8));
	return fnHmiRegWrite(HMIREG_RW_WDTIM_LOW, (unsigned char)value);
}

/**
* \brief Read Watchdog interval
*
* \param pretval pointer to readback value, 0 disables Watchdog
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_wdtim_read( int *pretval)
{
	int rc;
	int tval1,tval2;

	rc=fnHmiRegRead(HMIREG_RW_WDTIM_LOW, &tval1);
	if (rc!=0) return rc;
	rc=fnHmiRegRead(HMIREG_RW_WDTIM_HIGH, &tval2);
	if (rc!=0) return rc;
	*pretval=(((unsigned char)tval2)<<8)|((unsigned char)tval1);
	return 0;
}

/**
* \brief Configure Watchdog timeout action
*
* \param value 0..switch off backlight, 1..reset CPU
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_wdconf_write( unsigned char value)
{
	return fnHmiRegWrite(HMIREG_RW_WDCONF, value);
}

/**
* \brief Read Watchdog timeout action
*
* \param pretval pointer to readback value
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_wdconf_read( int *pretval)
{
	return fnHmiRegRead(HMIREG_RW_WDCONF, pretval);
}

/**
* \brief Trigger Watchdog in HMI
*
*
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_wd_trigger()
{
	return fnHmitrTgrWd();
}

//================ buzzer ================================================
/**
* \brief Write loudness of buzzer alarm
*
* \param value value to write
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
	
HMITRAPI_API int hmi_buzzeralarm_write( unsigned char value)
{
	return fnHmiRegWrite(HMIREG_RW_BUZZALRM, value);
}

/**
* \brief Read loudness of buzzer alarm
*
* \param pretval pointer to readback value
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_buzzeralarm_read( int *pretval)
{
	return fnHmiRegRead(HMIREG_RW_BUZZALRM, pretval);
}

/**
* \brief Write loudness of keypress click
*
* \param value value to write
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/
HMITRAPI_API int hmi_buzzerclick_write( unsigned char value)
{
	return fnHmiRegWrite(HMIREG_RW_BUZZCLICK, value);
}

/**
* \brief Read loudness of keypress click
*

* \param pretval pointer to readback value
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/

HMITRAPI_API int hmi_buzzerclick_read( int *pretval)
{
	return fnHmiRegRead(HMIREG_RW_BUZZCLICK, pretval);
}

//================ board id ================================================

/**
* \brief Read Board Identification
*
* \param pretval pointer to readback value
* \param which \n
*     0 .. Hardware ID \n
*     1 .. Hardware Function ID \n
*     2 .. Firmware Function ID \n
*     3 .. Firmware Revision ID \n
*
* \return 0 on Success \n
*	Error number, see hmi_errstring()
*/	
HMITRAPI_API int hmi_boardident_read( int which, int *pretval)
{
	int rc;
	int tval1,tval2;
	switch(which)
	{
		case 0: return fnHmiRegRead(HMIREG_R_HWID, pretval);
		case 1:
			rc=fnHmiRegRead(HMIREG_R_HWFUNCID_LOW, &tval1);
			if (rc!=0) return rc;
			rc=fnHmiRegRead(HMIREG_R_HWFUNCID_HIGH, &tval2);
			if (rc!=0) return rc;
			*pretval=(((unsigned char)tval2)<<8)|((unsigned char)tval1);
			return 0;
		case 2: return fnHmiRegRead(HMIREG_R_FWFUNCID, pretval);
		case 3: return fnHmiRegRead(HMIREG_R_FWREVID, pretval);
		default: break;
	}
	return HMIERR_EINVAL;
}

//================ reset ================================================
/**
* \brief Reset registers to factory default
*
*
* \return 0 on Success \n
*		Error number, see hmi_errstring()
*/


HMITRAPI_API int hmi_reset2default()
{
	return fnHmiRegWrite(HMIREG_RW_RESET2DEFAULT, 0);
}

