/*
Adam Orin's STV camera control, Fall 2005

The stuff written here is what I've learned in conjunction with the STV Command Protocol
documentation. If I were you, I would read through that before looking at this mess.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
PACKET DATA FORMAT
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Here is how the data format works
Byte 1 = 0xa5
Byte 2 = Command
Byte 3 = Number of data bytes (least sig byte)
Byte 4 = Number of data bytes (most sig byte)
Byte 5 = Header checksum (least sig byte)
Byte 6 = Header checksum (most sig byte)
Byte 7 = Data byte 1
Byte 8 = Bata byte 2
...
Byte 6+N = Data byte N
Byte 6+N+1 = Data checksum (least sig byte)
Byte 6+N+2 = Data checksum (most sig byte)


If a command takes in no data, it is 6 bytes long. If it takes data it is 8 bytes plus the number of data bytes long.

To calculate header checksum:  (byte1 + byte2 + byte3 + byte4) % 65536
-Add the 4 header bytes, the result is a 16 bit unsigned int
-Cut the 16 bit checksum into two 8 bit chunks
-Byte 5 = least sig half of the checksum
-Byte 6 = most sig half of the checksum

To calc data checksum: Same algorithm as header checksum, except performed on the data bytes.


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
COMMANDS, AND WHAT TO EXPECT FROM THE STV IN RETURN
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

!!Note = Command 0x10 Request Acknowledge doesn't work - don't know how much/what data to send

=-=-=-=-=-=-
SC_PRESS = press button.  Send in 2 bytes of data that are the button to push.  The STV will return an ACK packet (6 bytes)

=-=-=-=-=-=-
SC_ECHO = echo display.  Send 2 bytes of data, data[0] and data[1], int hat order. If data={1,0}, the STV will immediately return the display, and will return the display every time a button is pressed. The header returned is (0xa5 0x9 0x30 0x0 0xde 0x0), where 0x30 = dec48, the number of bytes in the data returned.  If data={0,0}, the STV will stop sending the display and returns seemingly nothing (the documentation says it returns an ACK, but it hasn't for me)

NOTE!! Although the STV seems to not reply when you send it data={0,0}, I've noticed display data in the computer's input buffer before.  There are inflush calls to prevent any screen data from being a problem, but I need to get to the bottom of this.

NOTE!! Sometimes, maybe about 30 percent of the time, the STV does reply to data={0,0} by sending the entire screen. Except, one of the characters int he screen that would have been a whitespace (HEX 20) is replaces by HEX A4, which represents nothing in ASCII, and the computer displays as a whitespace.


=-=-=-=-=-=-
SC_BUFSTAT = request flash buffer status.  STV responds with typical header junk, plus four data bytes that tell you which buffers have image data. That would be 12 bytes total that the STV will send you in response.


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
DOWNLOADING IMAGES FROM STV
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
To download an image stored in one of the STV's 31 flash buffers, it appears that you have to download it row by row.

NOTE!! You must request image info before STV will respond to a request for image data. At least, it seems that way. So, to download an image in buffer X, you send a request image info command.  The STV sends

NOTE!! It appears that the STV will not always let you download an image regardless of what state it's in. For example, once you download an image, the display often changes to "DOWNLOAD ALL".  If you request image info for a second image, you get nothing back.  But simply pressing the FILEOPS key, for example, seems to put the STV in a state that will allow it to send another image.

SC_REQIMGINFO = request image info.  You tell the STV which buffer you are interested in, and the STV send you 44 data bytes of info (apparently) plus the usual 8 bytes of header crap. That's 52 bytes total.

SC_REQIMG = request image data.  You ask the STV for a specific row of image data in a specific buffer, and the STV gives it to you, along with the normal 8 bytes of header crap. Looks like you have to go one row at a time, from row 0 to 199 (for a 320*200 image). I just set left=0; I think that's if you don't what the entire row. And, if you get the whole row of a 320*200 image, length = 320, not 319, dumass.


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
FOCUS MODE SENSITIVITY SETTINGS
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
01 = 1 ms exposure, 1x gain
02 = 1 ms, 1x  			?? Difference between 1 and 2?
03 = 3 ms, 1x
04 = 10 ms, 1x
05 = 20 ms, 1x
06 = 25 ms, 1x				!! This is the setting we often use when ranging
07 = 50 ms, 1x
08 = .10 s, 1x
09 = .25 s, 1x
10 = .25 s, 2x
11 = .25 s, 4x
12 = .25 s, 8x
13 = .25 s, 16x
14 = .50 s, 16x
15 = 1.0 s, 16x
16 = 2.5 s, 16x


*/

#define STVDEBUG          0       //Set to 1 for verbose output to stdout, 0 if you want nuthin
#define MADVERBOSITY      0       //Set to 1 along with STVDEBUG for stv_read and stv_send to spit out ALL bytes received to stdout

//Numbers I use
#define S_MAXSEND         1000     //Max number of bytes that can be sent
#define S_MAXRECEIVE      1000     //Max number of bytes that can be received
#define S_MAXWIDTH        640      //Max image width you can get
#define S_MAXHEIGHT       480      //Max image height you can get

#define S_STARTER         0xa5	//Every packet sent to STV starts with this

// C = It's a command code
#define SC_ACK            0x06	//Positive acknowledge
#define SC_NAK            0x15	//Negaitve acknowledge
#define SC_PRESS          0x08	//Press a key
#define SC_ECHO           0x09	//Return the display
#define SC_BUFSTAT        0x03	//Request buffer status
#define SC_REQIMGINFO     0x04	//Request image info
#define SC_REQIMG         0x05	//Request image data

//K = It's a keypress code
// For keypresses below, the digits to the left are the most sig
#define SK_CALIBRATE      0x1000
#define SK_TRACK          0x0200
#define SK_DISPLAY        0x0400
#define SK_FILEOPS        0x0800
#define SK_PARAMETER      0x0010  
#define SK_SETUP          0x0020
#define SK_VALUE          0x0040  
#define SK_INTERRUPT      0x0080
#define SK_FOCUS          0x0001
#define SK_IMAGE          0x0002
#define SK_MONITOR        0x0004
#define SK_LRDECREASE     0x8000
#define SK_LRINCREASE     0x4000
#define SK_UDDECREASE     0x2000
#define SK_UDINCREASE     0x1000
#define SK_SHIFT          0x0008


// Function stv_open-----------------------------------------------------------
// Return -1 if error, file descriptor otherwise
PUBLIC int stv_open() ;


// Function stv_close----------------------------------------------------------
// Return -1 if error, 0 otherwise
PUBLIC int stv_close(int fd) ;


/* 
 Function stv_readpacket-------------------------------------------------------
 Intended to be used where you would use the standard read() function
 Waits until you get num_databytes or until read() times out
 Returns number of bytes read in, or -1 for error

 int fd				Descriptor for the serial port the STV is connected to
 uint8 inbuf[]			Pointer to array where you want the read data stored
 uint16 num_bytes		Number of 8-bit bytes you expect to read in
*/
PRIVATE int stv_readpacket(int fd, uint8 inbuf[], uint16 num_bytes) ;


/*
 Function stv_send-------------------------------------------------------------
 Send command to STV, in approporiate format, with data if there is any to send
 Return -1 if error, # bytes sent otherwise

 int fd				Descriptor for the serial port the STV is connected to
 uint8 command			The command code you want sent
 uint8 data[]			Pointer to array that holds data that you want sent, if any
 uint16 num_databytes 	Number of data bytes to send, not including header and data checksum
*/
PRIVATE int stv_send(int fd, uint8 command, uint8 data[], uint16 num_databytes) ;


/*
 Function stv_read-------------------------------------------------------------
 Reads in data from the STV, and sticks it ALL (header + data checksum included) into data array
 Return -1 if error, # bytes received otherwise

 int fd				Descriptor for the serial port the STV is connected to
 uint8 data[]			Pointer to array where you want the data to be stored
					Function returns all bytes read in, including header and checksums
 uint16 num_databytes	Number of data bytes you want read in, if any (not including header junk)
*/
PRIVATE int stv_read(int fd, uint8 data[], uint16 num_databytes) ;


/*
 Function stv_presskey---------------------------------------------------------
 Simulates pushing a button of your choice on the STV.  STV returns with an ACK.
 Key codes are in header file
 Return 0 if error, 1 if successfully sent command AND STV resonds with ACK

 int fd				Descriptor for the serial port the STV is connected to
*/
PUBLIC int stv_presskey(int fd, uint16 key) ;


/*
 Function stv_ack--------------------------------------------------------------
 Waits for STV to return a positive ACK
 Return 1 if successfull, 0 if error

 int fd				Descriptor for the serial port the STV is connected to
*/
PUBLIC int stv_ack(int fd) ;


/*
 Function stv_getscreen--------------------------------------------------------
 Give this function a 50 byte array, and he'll fill it with the STV's screen
 Array disp must have 50+ elements to hold the screen (48 + newline + null)
 Return 1 if successfull, 0 if error

 int fd				Descriptor for the serial port the STV is connected to
 uint8 disp[]			Pointer to 50+ byte array to store the screen
*/
PUBLIC int stv_getscreen(int fd, uint8 disp[]) ;

/*
 Function stv_get_buffer_info--------------------------------------------------
 This function reads out which of the flash buffers (0-31) have image data,
 and outputs the data to a 32+ element array. fullbuffers[0]=1 means buffer
 0 has image data, etc.

 int fd				Descriptor for the serial port the STV is connected to
 int fullbuffers[]		pointer to 32+ element array to fill with buffer info
*/
PUBLIC int stv_get_buffer_info(int fd, uint16 fullbuffers[]) ;


/*
 Function stv_download_image---------------------------------------------------
 This function reads image stored in flashbuffer, 
 and saves image to file called imgname.out
 You better make sure the buffer contains data, or this function will croak!
 Return 1 if successfull, 0 if error

 int fd				Descriptor for the serial port the STV is connected to
 uint16 flashbuffer		Which buffer you want to download from (0-31)
 char imgname[]		String that you want the image called
*/
PUBLIC int stv_download_image(int fd, uint16 flashbuffer, char imgname[]) ;


/*
 Function stv_getdispimg-------------------------------------------------------
 This function reads image currently displayed (flash buffer 31), 
 and saves image to file called imgname.out
 Return 1 if successfull, 0 if error

 int fd				Descriptor for the serial port the STV is connected to
 char imgname[]		String that you want the image called
*/
PUBLIC int stv_getdispimg(int fd, char imgname[]) ;


/*
 Function stv_getallimg-------------------------------------------------------
 This function figures out which buffers have image data, and downloads all
 images. Output images are named imgname##.out, where ## is source buffer 
 Return 1 if successfull, 0 if error

 int fd				Descriptor for the serial port the STV is connected to
 char imgname[]		String that you want the images called
*/
PUBLIC int stv_getallimg(int fd, char imgname[]) ;


/*
 Function stv_writeimg------------------------------------------------------
 Called by stv_download_image
 Takes a 2D array of uint16s, and outputs an image file with name imgname.out
 (it adds the appropriate file extension to the string imgname)
 Return 1 if successfull, 0 if error

 Eventually will output a fits file or something cool.

 int fd				Descriptor for the serial port the STV is connected to
 int width			Width of image, in pixels
 int height			Height of image, in pixels

 uint16 imgarray[S_MAXWIDTH][S_MAXHEIGHT]
 The image array you want output.  You have to give it an array of size 
 S_MAXWIDTH * S_MAXHEIGHT.  So, your image array is organized imgarray[cols][rows]
*/
PRIVATE int stv_writeimg(char imgname[], int width, int height, uint16 imgarray[S_MAXWIDTH][S_MAXHEIGHT]) ;


/*
 Function stv_quickvid---------------------------------------------------------
 A little fuction that puts the STV into focus mode (25ms, 1X is sensitivity = 6)
 Sensitivity goes from 1 to 16. Function reads the display and will push the 
 appropriate buttons to get the thing into focus mode at the desired sensitivity.
 Return 1 if successfull, 0 if error

 int fd				Descriptor for the serial port the STV is connected to
 int desired_sens		What sensitivity you want (1 to 16)
*/
PUBLIC int stv_quickvid(int fd, int desired_sens) ;


/*
I did not draw this but I wish I did. I did not draw this but I wish I did. 
I did not draw this but I wish I did. I did not draw this but I wish I did. 
I did not draw this but I wish I did. I did not draw this but I wish I did. 


                          oooo$$$$$$$$$$$$oooo
                      oo$$$$$$$$$$$$$$$$$$$$$$$$o
                   oo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o         o$   $$ o$
   o $ oo        o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o       $$ $$ $$o$
oo $ $ "$      o$$$$$$$$$    $$$$$$$$$$$$$    $$$$$$$$$o       $$$o$$o$
"$$$$$$o$     o$$$$$$$$$      $$$$$$$$$$$      $$$$$$$$$$o    $$$$$$$$
  $$$$$$$    $$$$$$$$$$$      $$$$$$$$$$$      $$$$$$$$$$$$$$$$$$$$$$$
  $$$$$$$$$$$$$$$$$$$$$$$    $$$$$$$$$$$$$    $$$$$$$$$$$$$$  """$$$
   "$$$""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$     "$$$
    $$$   o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$     "$$$o
   o$$"   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$       $$$o
   $$$    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" "$$$$$$ooooo$$$$o
  o$$$oooo$$$$$  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$   o$$$$$$$$$$$$$$$$$
  $$$$$$$$"$$$$   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$     $$$$""""""""
 """"       $$$$    "$$$$$$$$$$$$$$$$$$$$$$$$$$$$"      o$$$
            "$$$o     """$$$$$$$$$$$$$$$$$$"$$"         $$$
              $$$o          "$$""$$$$$$""""           o$$$
               $$$$o                                o$$$"
                "$$$$o      o$$$$$$o"$$$$o        o$$$$
                  "$$$$$oo     ""$$$$o$$$$$o   o$$$$""
                     ""$$$$$oooo  "$$$o$$$$$$$$$"""
                        ""$$$$$$$oo $$$$$$$$$$
                                """"$$$$$$$$$$$
                                    $$$$$$$$$$$$
                                     $$$$$$$$$$"
                                      "$$$""""

*/


