/////////////////////////////////////////////////////////////////////////
////                                                                 ////
////                    Falcon4 ICP controler                        ////
////                            icp.c                                ////
////                                                                 ////
//// 15 Sept 2006: Initial release.                                  ////
////                                                                 ////
//// 05 Janv 2007: MFD support added throught I2C                    ////
/////////////////////////////////////////////////////////////////////////




#define __USB_PIC_PERIF__ 1

#include <18F2550.h>
//#include <18F2455.h>

#include "thumbwheel.h"
#include "bootloader.h"
#include "keymap.h"


#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,WRTB

#use delay(clock=48000000)

#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use I2C(master, sda=PIN_B0, scl=PIN_B1)


#include "icp.c"
#include "thumbwheel.c"
#include "mfd.c"



/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines.  For dynamic configuration of the CCS Library
// for your application several defines need to be made.  See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////

//Tells the CCS PIC USB firmware to include HID handling code.
#DEFINE USB_HID_DEVICE  TRUE

//the following defines needed for the CCS USB PIC driver to enable the TX endpoint 1
#define USB_EP1_TX_ENABLE  USB_ENABLE_INTERRUPT   //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8

#define USB_EP2_TX_ENABLE  USB_ENABLE_INTERRUPT   //turn on EP2 for IN bulk/interrupt transfers
#define USB_EP2_TX_SIZE 8

#define USB_EP2_RX_ENABLE  USB_ENABLE_INTERRUPT   //turn on EP2 for IN bulk/interrupt transfers
#define USB_EP2_RX_SIZE 4


/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.  See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h>
#include <falcon4.h>    //USB Configuration and Device descriptors for this UBS device
#include <usb.c>    //handles usb setup tokens and get descriptor reports


/////////////////////////////////////////////////////////////////////////////
//
// usb_keyboard_task()
//
// Sends a packet of keyboard data.  The protocol was specified in the HID
// report descriptor (see usb_desc_kbmouse.h), and is:
//     tx_msg[0] = modifier (an 8bit bitmap of shift, tab, alt keypress)
//                           b7   b6   b5    b4       b3   b2   b1    b0
//                               Right hand               Left hand
//                           GUI,ALT,SHIFT,CTRL       GUI,ALT,SHIFT,CTRL
//     tx_msg[1] = const 0
//     tx_msg[2:6] = an array of held down keys.  a=4, b=5, etc.
//                   if msg[2:7]={0} then no keys are held down
//
//     rx_msg[0] = 5bit bitmap of led status
//
/////////////////////////////////////////////////////////////////////////////
void main(void) {
  static int8 tx_msg[7]={0,0,0,0,0,0,0};
  static int8 TxUSB[5]={0,0,0,0,0};
  static int8 leds;
  static int8 data;

  int nb_keys;
  int i;

  printf("\r\n*********************************************************************");
  printf("\r\n*        Falcon4 ICP controler                                      *");
  printf("\r\n* Under GNU License                                                 *");
  printf("\r\n* check http://www.opensource.org/                                  *");
  printf("\r\n* project by Nicolas Camil                                          *");
  printf("\r\n* http://n.camil.chez.tiscali.fr                                    *");
  printf("\r\n* ----------------------------------------------------------------- *");
  printf("\r\n*                                                                   *");
  printf("\r\n* This library is free software; you can redistribute it and/or     *");
  printf("\r\n* modify it under the terms of the GNU Library General Public       *");
  printf("\r\n* License as published by the Free Software Foundation.             *");
  printf("\r\n*                                                                   *");
  printf("\r\n* This library is distributed in the hope that it will be useful,   *");
  printf("\r\n* but WITHOUT ANY WARRANTY; without even the implied warranty of    *");
  printf("\r\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *");
  printf("\r\n* Library General Public License for more details.}                 *");
  printf("\r\n*********************************************************************");


  usb_init_cs();

  printf("\r\n");

  while (TRUE) {
    usb_task();

    if (usb_enumerated()) {
      //ICP
      nb_keys = icp_task();
      for (i=0;i<nb_keys;++i){
        switch (icp_keys[i].pos){
          case kpDwn :
            printf("\r\nKey #%u down [%u][%u]", i, icp_keys[i].lign, icp_keys[i].col);
            icp_keys[i].lign = 5 - icp_keys[i].lign;
            tx_msg[0] = icp_keymaps[icp_keys[i].lign] [icp_keys[i].col].modifier;
            tx_msg[2] = icp_keymaps[icp_keys[i].lign] [icp_keys[i].col].key_hid;
            printf("\r\nF4 code=%x mod=%x", icp_keymaps[icp_keys[i].lign] [icp_keys[i].col].key_hid, icp_keymaps[icp_keys[i].lign] [icp_keys[i].col].modifier);
            break;

          case kpUp :
            printf("\r\nKey #%u up   [%u][%u]", i, icp_keys[i].lign, icp_keys[i].col);
            tx_msg[0] = 0;
            tx_msg[2] = 0;
            break;

        }//end switch
        usb_put_packet(2,tx_msg,sizeof(tx_msg),USB_DTS_TOGGLE);
      }
      //receive NUM LOCK, CAPS LOCK, etc LED status from PC.
      //we won't do anything with it.
      if (usb_kbhit(2)) {
         usb_get_packet(2, &leds, 1);
      }


      //Tumbwheels
      if (thumbweel_task()) {
        TxUSB[0] = 0x00FF & TW1;
        TxUSB[1] = (TW1 >> 8) | ((TW2 & 0x3F) << 2);
        TxUSB[2] = (TW2 >> 6) | ((TW3 & 0x0F) << 4);
        TxUSB[3] = (TW3 >> 4) | ((TW4 & 0x03) << 6);
        TxUSB[4] = (TW4 >> 2);
        //printf("\r\nadc vals [%Lu %Lu %Lu %Lu]  usb[%u %u %u %u %u]", TW4, TW3, TW2, TW1, TxUSB[4], TxUSB[3], TxUSB[2], TxUSB[1], TxUSB[0]);
        //printf("0");

        usb_put_packet(1,TxUSB,sizeof(TxUSB),USB_DTS_TOGGLE);
      }

      //MFD
      nb_keys = mfd_task();
      for (i=0;i<nb_keys;++i){
        switch (mfd_keys[i].pos){
          case kpDwn :
            printf("\r\nKey #%u down [%u][%u]", i, mfd_keys[i].lign, mfd_keys[i].col);
            tx_msg[0] = mfd_keymaps[mfd_keys[i].lign] [mfd_keys[i].col].modifier;
            tx_msg[2] = mfd_keymaps[mfd_keys[i].lign] [mfd_keys[i].col].key_hid;
            printf("\r\nF4 down[%u][%u]   code=%x mod=%x", mfd_keys[i].lign, mfd_keys[i].col, mfd_keymaps[mfd_keys[i].lign] [mfd_keys[i].col].key_hid, mfd_keymaps[mfd_keys[i].lign] [mfd_keys[i].col].modifier);
            break;

          case kpUp :
            printf("\r\nKey #%u up   [%u][%u]", i, mfd_keys[i].lign, mfd_keys[i].col);
            tx_msg[0] = 0;
            tx_msg[2] = 0;
            break;

        }//end switch
        usb_put_packet(2,tx_msg,sizeof(tx_msg),USB_DTS_TOGGLE);
      }
    } else
      delay_ms(10);
  }
}

