/*
**
** FILE: combi.c
**
**
** purpose: USB firmware for Cypress USB/PS2 mouse reference design
**
**
** revision history:
** 6/27/00 bth : modified ps2 scaling algorithm
** 7/11/00 sea : modified ps2 resolution constants and
** ps2_send() start bit inhibit response
**
*/
#pragma option INSTRUCTIONTIMING //needed for Cypress debugger to work properly
#pragma option f0 //do not insert page breaks in listing file
#pragma option REGSAVEOFF; //do not automatically save AC and IX in interrupts
#pragma option NOINIT;
#define DEBUG
#include "chip.h"
#include "usbdefs.h"
#include "ps2defs.h"
#define BIT0 1
#define BIT1 2
#define BIT2 4
#define BIT3 8
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
//*************************************************************************************************
//USER_DEFINES
/*
**
** the following defines can be changed to accomodate different I/O pinouts. It is assumed that
** all 6 quadrature inputs (optics) are connected to the same port.
**
*/
#define OPTICS_PORT PORT0 //optics port
#define OPTICS_MASK 0x3f //mask of all optics inputs
/*
** for each set of x,y, and z optics, define a macro that will move the corresponding 2 quadrature bits
** into bit1 and bit0. For instance, in the reference design
** the y- quadrature inputs are at bits 3 and 2, so the macro shifts the bits by 2 and
** masks them.
*/
#define GET_X_OPTICS(x) ((x >> 0) & 0x3) //no shift necessary
#define GET_Y_OPTICS(x) ((x >> 2) & 0x3) //shift bits [3:2] into [1:0]
#define GET_Z_OPTICS(x) ((x >> 4) & 0x3) //shift bits [5:4] into [1:0]
/*
** define each switch's port and bit position
*/
#define LEFT_SWITCH_PORT PORT0
#define LEFT_SWITCH_MASK BIT7
#define RIGHT_SWITCH_PORT PORT1
#define RIGHT_SWITCH_MASK BIT0
#define MIDDLE_SWITCH_PORT PORT1
#define MIDDLE_SWITCH_MASK BIT1
/*
**define masks for the port pin functions. This information is used to establish the mode
**settings for the GPIO pins
**
*/
#define PORT0_OPTICS_MASK 0b00111111 //optics pins [5:0] on port 0
#define PORT1_OPTICS_MASK 0b00000000 //no optics on port 1
#define PORT0_LED_MASK 0b01000000 //led drive at pin [6] on port 0
#define PORT1_LED_MASK 0b00000000 //no led drive on port 1
#define PORT0_SWITCH_MASK 0b10000000 //switch input at pin [7] on port 0
#define PORT1_SWITCH_MASK 0b00000011 //switch inputs at [1:0] on port 1
//comment the following lines if you do not want PS2 resolution and scaling commands to be implemented
//in the code.
#define ENABLE_RESOLUTION
#define ENABLE_SCALING
//END OF USER DEFINES
//*************************************************************************************************
//*************************************************************************************************
//COMMON DECLARATIONS USED BY BOTH INTERFACES
#include "macros.h" //include macro definitions
/*
** define port data and mode initial values for the 3 operating states -- normal, suspend, and suspend with remote
** wakeup -- based on the masks provided by the user
*/
/*
**normal operating mode
*/
#define PORT0_INIT PORT0_SWITCH_MASK
#define PORT1_INIT PORT1_SWITCH_MASK
#define PORT0_MODE1_INIT PORT0_SWITCH_MASK
#define PORT1_MODE1_INIT PORT1_SWITCH_MASK
#define PORT0_MODE0_INIT PORT0_LED_MASK
#define PORT1_MODE0_INIT PORT1_LED_MASK
/*
** suspend mode (no remote wakeup)
*/
#define PORT0_SUSPEND PORT0_LED_MASK
#define PORT1_SUSPEND PORT1_LED_MASK
#define PORT0_MODE1_SUSPEND PORT0_LED_MASK
#define PORT1_MODE1_SUSPEND PORT1_LED_MASK
#define PORT0_MODE0_SUSPEND PORT0_SWITCH_MASK
#define PORT1_MODE0_SUSPEND PORT1_SWITCH_MASK
/*
** remote wakeup
*/
#define PORT0_RW (PORT0_LED_MASK | PORT0_SWITCH_MASK)
#define PORT1_RW (PORT1_LED_MASK | PORT1_SWITCH_MASK)
#define PORT0_MODE1_RW (PORT0_SWITCH_MASK | PORT0_LED_MASK)
#define PORT1_MODE1_RW (PORT1_SWITCH_MASK | PORT1_LED_MASK)
#define PORT0_MODE0_RW 0
#define PORT1_MODE0_RW 0
#define LEFT_SWITCH_ASSERTED (!(LEFT_SWITCH_PORT & LEFT_SWITCH_MASK))
#define MIDDLE_SWITCH_ASSERTED (!(MIDDLE_SWITCH_PORT & MIDDLE_SWITCH_MASK))
#define RIGHT_SWITCH_ASSERTED (!(RIGHT_SWITCH_PORT & RIGHT_SWITCH_MASK))
/*
** switches are debounced in a routine that is called every 4 msec. 10
** successive stable samples are required for a switch change to be reported.
*/
#define DEBOUNCE_COUNT 10 //10 identical samples must be taken to recognize switch changes
/*
** define a structure containing variables updated in the 1-msec interrupt
*/
typedef struct
{
char b1msCounter; //incremented inside 1msec interrupt for general timing
char b1msFlags; //flag set inside 1msec interrupt
}ONE_MSEC_STATUS;
#define ONE_MSEC_FLAG 1
/*
** Quadrature inputs are sampled inside the 128 usec interrupt and placed in a queue for later
** processing in the main loop.
**
*/
typedef struct
{
char near *headP; //head of queue
char near *tailP; //tail of queue
char bLen; //length of queue
}QUEUE_STRUCT;
/*
** current state of each quadrature pair is stored to compare with the next sample.
**
*/
typedef struct
{
char bXstate; //current state of X optics
char bYstate; //current state of Y optics
char bZstate; //current state of Z optics
}OPTICS_STATE;
/*
** the order of the bytes in this structure is important! These bytes are in the
** proper order for a packet returned to a USB host in response to a Get_Report command.
*/
typedef struct
{
char bChange; //set to 1 if mouse state has changed
char bButtons; //current state of mouse buttons
signed char bXcount; //current accumulation of X counts
signed char bYcount; //current accumulation of Y counts
signed char bZcount; //current accumulation of Z counts
}MOUSE_STATE;
/*
** global variables used by both USB and PS2 interfaces
*/
QUEUE_STRUCT OpticsQueue; //optics queue
ONE_MSEC_STATUS MsecStatus; //status of 1msec interrupt
OPTICS_STATE Optics; //current state of optics
MOUSE_STATE Mouse; //current state of mouse (buttons, x,y,z)
char bLastButtons;
char bDebounceCount;
char bOpticsArray[16]; //16-byte array used for optics queue data
const signed char quad_table[] =
/*
;***
; Quadrature state table. This table assists processing of quadrature state
; transitions. The table index is calculated as:
; [(last_state)*4 + current_state],
; and the table entry at that point is 1, 0 or -1 indicating increment, hold
; or decrement the count, respectively.
;***
*/
{
0, //;State 0 => state 0 (NoChange)
1, //; => state 1 (Increment)
0xff, //; => state 2 (Decrement)
0, //; => state 3 (Fault)
0xff, //;State 1 => state 0 (Decrement)
0, //; => state 1 (NoChange)
0, //; => state 2 (Fault)
1, //; => state 3 (Increment)
1, //;State 2 => state 0 (Increment)
0, //; => state 1 (Fault)
0, //; => state 2 (NoChange)
0xff, //; => state 3 (Decrement)
0, //;State 3 => state 0 (Fault)
0xff, //; => state 1 (Decrement)
1, //; => state 2 (Increment)
0 //; => state 3 (NoChange)
};
const signed char z_quad_table[] =
/*
;***
; Quadrature state table. This table assists processing of quadrature state
; transitions. The table index is calculated as:
; [(last_state)*4 + current_state],
; and the table entry at that point is 1, 0 or -1 indicating increment, hold
; or decrement the count, respectively.
;***
*/
{
0, //;State 0 => state 0 (NoChange)
0, //; => state 1 (NoChange)
0, //; => state