/** INCLUDES *******************************************************/
#include "GenericTypeDefs.h"
#include "Compiler.h"
#include "HardwareProfile.h"
#include "USB/usb.h"
#include "usbavrcmd.h"
#include "user.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined (UBW)
#include <delays.h>
#include <i2c.h>
#include <EEP.h>
#elif defined (UBW32)
#include <peripheral/i2c.h>
#include <dee_emulation/dee_emulation_pic32.h>
#endif
/********************************************************************
* Section B: EP0 Buffer Space
*******************************************************************/
extern volatile CTRL_TRF_SETUP SetupPkt; // 8-byte only
extern volatile BYTE CtrlTrfData[USB_EP0_BUFF_SIZE];
#pragma udata
WORD_VAL FilterCrossOver[8];
float FilterSwitchOver[7];
WORD_VAL LPFCrossOver[8];
float LPFSwitchOver[7];
#pragma code
void USBCheckUBWRequest(void)
{
unsigned char paddle_byte;
unsigned int eep_adr;
WORD_VAL w;
unsigned int i, j;
unsigned char IO_data;
#if defined (UBW32)
unsigned int value;
unsigned int number_of_filter_bytes;
#else
unsigned char number_of_filter_bytes;
#endif
if(SetupPkt.RequestType == USB_SETUP_TYPE_STANDARD_BITFIELD) return; // only deals with non-standard, ie user requests
command = SetupPkt.bRequest; // save the command of the user request from the setuppacket
// it will be used for subsequent data transfer
switch(command)
{
case CMD_GET_CW_KEY:
paddle_byte = 0x22; // 00100010
if (!PADDLE_DIT) paddle_byte &= 0xdf; // 11011111
if (!PADDLE_DAH) paddle_byte &= 0xfd; // 11111101
if (RXTX) paddle_byte |= 0x10; // PB4 is the ATTINY PTT_OUT pin 00010000
else paddle_byte &= 0xef; // 11101111
replybuf[0] = paddle_byte;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_SET_USRP1: // Set RxTx and get Paddle status
paddle_byte = 0x22; // 00100010
if ( SetupPkt.W_Value.v[0] ){
RXTX = 1; // Set PTT
paddle_byte |= 0x10; // 00010000
}
else{
RXTX = 0;
paddle_byte &= 0xef; // 11101111
};
if (!PADDLE_DIT) paddle_byte &= 0xdf; // 11011111
if (!PADDLE_DAH) paddle_byte &= 0xfd; // 11111101
replybuf[0] = paddle_byte;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_SET_FREQ_REG: // Control Transfer Rx of data from HOST->UBW
case CMD_SET_LO_SM:
case CMD_SET_FREQ:
case CMD_SET_XTAL:
case CMD_SET_STARTUP:
case CMD_SET_PPM:
wCount = SetupPkt.wLength;
outPipes[0].wCount.Val = SetupPkt.wLength;
outPipes[0].pFunc = &Read_Command_Into_Buffer;
outPipes[0].pDst.bRam = (BYTE*) &command_buffer[current_command_in].data[0];
outPipes[0].info.bits.busy = 1;
break;
case CMD_GET_PIN: // read ports
IO_data = 0x0d; // 00001101
if (PADDLE_DAH) IO_data |= 0x02; // PB1
if (BPF_S0_STATE) IO_data |= 0x10; // PB4
if (BPF_S1_STATE) IO_data |= 0x20; // PB5
replybuf[0] = IO_data;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_SET_PORT: // set ports
IO_data = SetupPkt.W_Value.v[0];
if (!abpf_flag){
if (IO_data & 0x10) BPF_S0 = 1;
else BPF_S0 = 0;
if (IO_data & 0x20) BPF_S1 = 1;
else BPF_S1 = 0;
};
break;
case CMD_SET_IO: // set i/o bits
IO_data = SetupPkt.W_Index.v[0] & 0x03; // only 2 bits active 00000011
if (!abpf_flag) { // abpf inactive
if (IO_data & 0x01) BPF_S0 = 1; // Simulate IO_PIN1 in ATTINY
else BPF_S0 = 0;
if (IO_data & 0x02) BPF_S1 = 1; // Simulate IO_PIN2 in ATTINY
else BPF_S1 = 0;
}
IO_data = BPF_S0_STATE; // read back status of BPF select pins
if (BPF_S1_STATE) IO_data |= 0x02;
else IO_data &= 0x01;
replybuf[0] = IO_data;
replybuf[1] = 0x00;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 2; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_IO:
IO_data = BPF_S0_STATE; // status of BPF select pins
if (BPF_S1_STATE) IO_data |= 0x02;
else IO_data &= 0x01;
replybuf[0] = IO_data;
replybuf[1] = 0x00;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 2; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_SET_FILTER: // Set and Read filter crossover points
i = SetupPkt.W_Index.Val;
if (i < 256){ // Rx Filter
number_of_filter_bytes = NUM_BPF * 2;
inPipes[0].pSrc.bRam = (BYTE*)&FilterCrossOver[0]; // Set source
if (i < NUM_BPF) {
FilterCrossOver[i].Val = SetupPkt.W_Value.Val;
if (i != (NUM_BPF-1)) FilterSwitchOver[i] = Cross2Switch(FilterCrossOver[i]);
else abpf_flag = SetupPkt.W_Value.Val;
}
}
else{ // Tx filter
number_of_filter_bytes = 16;
inPipes[0].pSrc.bRam = (BYTE*)&LPFCrossOver[0]; // Set source
j = i - 256;
if ( j < 8){
LPFCrossOver[j].Val = SetupPkt.W_Value.Val;
if (j != 7) LPFSwitchOver[j] = Cross2Switch(LPFCrossOver[j]);
};
};
// now that a filter value of filter enable/disable value is set, update the EEPROM
#if defined (UBW)
for (i = 0; i < NUM_BPF; i++){
Write_b_eep((i * 2 + F_CROSS_OVER +1), FilterCrossOver[i].v[0]);
Busy_eep();
Write_b_eep((i * 2 + F_CROSS_OVER + 1 + 1), FilterCrossOver[i].v[1]);
Busy_eep();
}
#elif defined (UBW32)
for (i =0; i < NUM_BPF; i++) DataEEWrite( FilterCrossOver[i].Val , (i + F_CROSS_OVER +1));
#endif
#if defined (UBW)
for (j = 0; j < 8; j++){
Write_b_eep(( j * 2 + F_CROSS_OVER +17), LPFCrossOver[j].v[0]);
Busy_eep();
Write_b_eep(( j * 2 + F_CROSS_OVER +17 + 1), LPFCrossOver[j].v[1]);
Busy_eep();
}
Write_b_eep(F_CROSS_OVER, F_CROSS_OVER_VALUE);
Busy_eep();
#elif defined (UBW32)
for (j = 0; j < 8; j++){
DataEEWrite( (unsigned int)LPFCrossOver[j].Val , (j + F_CROSS_OVER +9));
};
DataEEWrite(F_CROSS_OVER_VALUE, F_CROSS_OVER);
#endif
inPipes[0].wCount.v[0] = number_of_filter_bytes; // Set data count
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].info.bits.busy = 1;
break;
case CMD_SET_SI570: // SI570: write byte from register index
i2c_adr = SetupPkt.W_Value.v[0];
#if defined (UBW)
IdleI2C();
StartI2C();
IdleI2C();
WriteI2C( i2c_adr <<1);
WriteI2C( SetupPkt.W_Value.v[1]); // register = byte 3
WriteI2C( SetupPkt.W_Index.v[0]); // value to write to register
StopI2C();
IdleI2C();
#elif defined (UBW32)
IdleI2C1();
StartI2C1();
IdleI2C1();
MasterWriteI2C1( i2c_adr <<1);
MasterWriteI2C1( SetupPkt.W_Value.v[1]); // register = byte 3
MasterWriteI2C1( SetupPkt.W_Index.v[0]); // value to write to register
StopI2C1();
IdleI2C1();
#endif
replybuf[0] = 0; // just say no errors
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_LO_SM: // return sub mul
for (i=0; i<4; i++) replybuf[i] = f_sub.bytes[i];
for (i=0; i<4; i++) replybuf[i+4] = f_mul.bytes[i];
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 8; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_FREQ: // return set freq, ie no offset/mul
avr_freq.qw = set_frequency * (double)(1L << 21);
inPipes[0].pSrc.bRam = (BYTE*)&avr_freq.bytes[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 4; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_PPM: // return smooth tune in ppm
w.Val = Smooth_double * 1000000L;
inPipes[0].pSrc.bRam = (BYTE*)&w.v[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 2; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_STARTUP: // return init startup freq
#if defined(UBW)
for (i=0; i<4; i++) avr_freq.bytes[i] = Read_b_eep(i + F_INIT_FREQ +1);
#elif defined(UBW32)
for (i=0; i<4; i++) {
DataEERead(&value, (i + F_INIT_FREQ +1));
avr_freq.bytes[i] = value;
};
#endif
inPipes[0].pSrc.bRam = (BYTE*)&avr_freq.bytes[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 4; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_XTAL: // return fcryst
inPipes[0].pSrc.bRam = (BYTE*)&fcryst_freq.bytes[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 4; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_SI570: // SI570: read out frequency control registers
i2c_adr = SetupPkt.W_Value.v[0];
ReadRegs();
inPipes[0].pSrc.bRam = (BYTE*)®isters[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 6; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_I2C_ERR: // return # of i2c errors, set to zero always
replybuf[0] = 0; // No errors :)
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_SET_I2C_ADDR: // Reset EEPROM to default values if 255
// Otherwise just set i2c address
if (SetupPkt.W_Value.v[0] == 0xff){
#if defined (UBW)
Write_b_eep(F_CAL_DONE, 0xff);
Busy_eep();
Write_b_eep(F_INIT_FREQ, 0xff);
Busy_eep();
Write_b_eep(F_SMOOTH, 0xff);
Busy_eep();
Write_b_eep(F_SUB_MUL, 0xff);
Busy_eep();
Write_b_eep(F_CROSS_OVER, 0xff);
Busy_eep();
#elif defined (UBW32)
DataEEWrite( (unsigned int) 0xff, F_CAL_DONE);
DataEEWrite( (unsigned int) 0xff, F_INIT_FREQ);
DataEEWrite( (unsigned int) 0xff, F_SMOOTH);
DataEEWrite( (unsigned int) 0xff, F_SUB_MUL);
DataEEWrite( (unsigned int) 0xff, F_CROSS_OVER);
#endif
i2c_adr = 0x55;
}
else {
i2c_adr = SetupPkt.W_Value.v[0];
};
replybuf[0] = 0x00;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
case CMD_GET_VERSION: // return version 15.10
replybuf[0] = VERSION_MINOR;
replybuf[1] = VERSION_MAJOR;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0]; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 2; // Set data count
inPipes[0].info.bits.busy = 1;
break;
default: // Command not supported
replybuf[0] = 0xff;
inPipes[0].pSrc.bRam = (BYTE*)&replybuf[0] ; // Set Source
inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
inPipes[0].wCount.v[0] = 1; // Set data count
inPipes[0].info.bits.busy = 1;
break;
}//end switch
}
void Read_Command_Into_Buffer(void)
{
if (command_count >= COMMAND_BUFFER_SIZE){ // buffer full
current_command_out++; // discards oldest command
if (current_command_out >= COMMAND_BUFFER_SIZE) current_command_out = 0;
command_count--; // now one command less (discarded)
};
command_buffer[current_command_in].command = command;
command_buffer[current_command_in].wCount = wCount;
// data already copied to command_buffer before this outpipe pFunc is called
current_command_in++;
if (current_command_in >= COMMAND_BUFFER_SIZE) current_command_in = 0;
command_count++;
}