//---------------------------------------------------------------------------
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of Dallas Semiconductor
// shall not be used except as stated in the Dallas Semiconductor
// Branding Policy.
//--------------------------------------------------------------------------
//
//  swt12.c - Modifies Channel A and B and returns info byte data for
//            the DS2406 and DS2407.
//  version 2.00


// Include files
#include <stdio.h>
#include "ownet.h"
#include "swt12.h"

//----------------------------------------------------------------------
//  SUBROUTINE - ReadSwitch12
//
//	This routine gets the Channel Info Byte and returns it.
//
// 'portnum'       - number 0 to MAX_PORTNUM-1.  This number was provided to
//                   OpenCOM to indicate the port number.
//	'ClearActivity' - To reset the button
//
//	Returns: (-1) If the Channel Info Byte could not be read.
//			 (Info Byte) If the Channel Info Byte could be read.
//
int ReadSwitch12(int portnum, int ClearActivity)
{
   int rt=-1;			   //this is the return value depending if the byte was read
   int trans_cnt=0;		//this is the counter for the number of bytes to send
   uchar transfer[30];	//this is the whole block of byte info
   ushort lastcrc16;

   // access and verify it is there
   if (owAccess(portnum))
   {
      // reset CRC
      setcrc16(portnum,0);

      // channel access command
	   transfer[trans_cnt++] = 0xF5;
      lastcrc16 = docrc16(portnum,0xF5);

      // control bytes
      if (ClearActivity)
      {
		   transfer[trans_cnt++] = 0xD5;
         lastcrc16 = docrc16(portnum,0xD5);
      }
      else
      {
		   transfer[trans_cnt++] = 0x55;
         lastcrc16 = docrc16(portnum,0x55);
      }

	   transfer[trans_cnt++] = 0xFF;
      lastcrc16 = docrc16(portnum,0xFF);

      // read the info byte
	   transfer[trans_cnt++] = 0xFF;

	   // dummy data
	   transfer[trans_cnt++] = 0xFF;
	   transfer[trans_cnt++] = 0xFF;
	   transfer[trans_cnt++] = 0xFF;

      if (owBlock(portnum,FALSE,transfer,trans_cnt))
      {
		   rt = transfer[3];
		   // read a dummy read byte and CRC16
		   lastcrc16 = docrc16(portnum,transfer[trans_cnt-4]);
		   lastcrc16 = docrc16(portnum,transfer[trans_cnt-3]);
		   lastcrc16 = docrc16(portnum,transfer[trans_cnt-2]);
         lastcrc16 = docrc16(portnum,transfer[trans_cnt-1]);
		   if(lastcrc16 != 0xB001)
            rt = -1;
      }
   }
   else
      rt = -1;

   return rt;
}

//----------------------------------------------------------------------
//	SUBROUTINE - SetSwitch12
//
//  This routine sets the channel state of the specified DS2406
//
// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number was provided to
//                 OpenCOM to indicate the port number.
// 'SerialNum'   - Serial Number of DS2406 to set the switch state
// 'State'       - Is a type containing what to set A and/or B to.  It
//				   also contains the other fields that maybe written later
//
//  Returns: TRUE(1)  State of DS2406 set and verified
//           FALSE(0) could not set the DS2406, perhaps device is not
//                    in contact
//
int SetSwitch12(int portnum, uchar *SerialNum, SwitchProps State)
{
   ushort st;
   int rt=FALSE;
   uchar send_block[30];
   int send_cnt=0;
   ushort lastcrc16;

   setcrc16(portnum,0);

   // set the device serial number to the counter device
   owSerialNum(portnum,SerialNum,FALSE);

   // access the device
   if (owAccess(portnum))
   {
      // create a block to send that reads the counter
      // write status command
      send_block[send_cnt++] = 0x55;
      lastcrc16 = docrc16(portnum,0x55);

      // address of switch state
      send_block[send_cnt++] = 0x07;
      lastcrc16 = docrc16(portnum,0x07);
      send_block[send_cnt++] = 0x00;
      lastcrc16 = docrc16(portnum,0x00);

      // write state
	   st = 0x1F;
	   if(!State.Chan_B) st |= 0x40;
	   if(!State.Chan_A) st |= 0x20;
	   // more ifs can be added here for the other fields.

      send_block[send_cnt++] = (uchar)st;
	   lastcrc16 = docrc16(portnum,st);

      // read CRC16
      send_block[send_cnt++] = 0xFF;
      send_block[send_cnt++] = 0xFF;

      // now send the block
      if (owBlock(portnum,FALSE,send_block,send_cnt))
      {
         // perform the CRC16 on the last 2 bytes of packet
         lastcrc16 = docrc16(portnum,send_block[send_cnt-2]);
         lastcrc16 = docrc16(portnum,send_block[send_cnt-1]);

         // verify crc16 is correct
         if(lastcrc16 == 0xB001)
            rt = TRUE;
      }
   }

   // return the result flag rt
   return rt;
}


//----------------------------------------------------------------------
//	SUBROUTINE - SwitchStateToString12
//
//  This routine uses the info byte to return a string with all the data.
//
// 'infobyte'   - This is the information byte data from the hardware.
// 'outstr'     - This will be the output string.  It gets set in the
//				      the procedure.
//
// return the length of the string
//
int SwitchStateToString12(int infobyte, char *outstr)
{

   int cnt = 0;

   if(infobyte & 0x40)
   {
		cnt += sprintf(outstr+cnt, "%s", "Channel A and B\n");

	   if(infobyte & 0x80)
		   cnt += sprintf(outstr+cnt, "%s", "Supply\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "No Supply\n");

	   if(infobyte & 0x20)
		   cnt += sprintf(outstr+cnt, "%s", "Activity on PIO-B\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "No activity on PIO-B\n");

	   if(infobyte & 0x10)
		   cnt += sprintf(outstr+cnt, "%s", "Activity on PIO-A\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "No activity on PIO-A\n");

	   if(infobyte & 0x08)
		   cnt += sprintf(outstr+cnt, "%s", "Hi level on PIO B\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "Lo level on PIO B\n");

	   if(infobyte & 0x04)
		   cnt += sprintf(outstr+cnt, "%s", "Hi level on PIO A\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "Lo level on PIO A\n");

	   if(infobyte & 0x02)
		   cnt += sprintf(outstr+cnt, "%s", "Channel B off\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "Channel B on\n");

	   if(infobyte & 0x01)
		   cnt += sprintf(outstr+cnt, "%s", "Channel A off\n");
	   else
	  	   cnt += sprintf(outstr+cnt, "%s", "Channel A on\n");
   }
	else
   {
		cnt += sprintf(outstr+cnt, "%s", "Channel A\n");

	   if(infobyte & 0x80)
		   cnt += sprintf(outstr+cnt, "%s", "Supply\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "No Supply\n");

	   if(infobyte & 0x10)
		   cnt += sprintf(outstr+cnt, "%s", "Activity on PIO-A\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "No activity on PIO-A\n");

	   if(infobyte & 0x04)
		   cnt += sprintf(outstr+cnt, "%s", "Hi level on PIO A\n");
	   else
		   cnt += sprintf(outstr+cnt, "%s", "Lo level on PIO A\n");

	   if(infobyte & 0x01)
		   cnt += sprintf(outstr+cnt, "%s", "Channel A off\n");
	   else
	  	   cnt += sprintf(outstr+cnt, "%s", "Channel A on\n");

   }

   return cnt;
}


