diff --git a/firmware/source/buffer.c b/firmware/source/buffer.c index cc1fce4..b4e7da1 100644 --- a/firmware/source/buffer.c +++ b/firmware/source/buffer.c @@ -1,40 +1,105 @@ #include "buffer.h" -//typedef struct buffer{ -// uint8_t *data; //pointer to base buffer's allocated sram -// uint8_t size; //size of buffer in bytes (max 256 bytes) -// uint8_t status; //current status of buffer USB load/unload, flashing, waiting, erase -// uint8_t cur_byte; //byte currently being loaded/unloaded/flashed/read -// uint8_t reload; //add this number to page_num for next loading -// uint8_t buff_num; //address bits between buffer size and page number -// //ie need 2x128 byte buffers making buff_num = A7 -// //ie need 4x64 byte buffers making buff_num = A7:6 -// //ie need 8x32 byte buffers making buff_num = A7:5 -// uint16_t page_num; //address bits beyond buffer's size and buff_num A23-A8 -// //MSB A23-16, LSB A15-8 -// uint8_t mem_type; //SNES ROM, SNES RAM, PRG ROM, PRG RAM, CHR ROM, CHR RAM, CPLD, SPI -// uint8_t part_num; //used to define unlock commands, sector erase, etc -// uint8_t multiple; //number of times to program this page -// uint8_t add_mult; //add this number to page_num for multiple programs -// //CHR shift LSb to A13 (max 2MByte) -// //PRG shift LSb to A14 (max 4MByte) -// //SNES add to MSB of page_num (max 16MByte) -// uint8_t mapper; //mapper number of board -// uint8_t mapvar; //mapper variant -// uint8_t function; //function "pointer" for flash/dump operation control -//}buffer; - -//max raw buffer size is 256 bytes must create multiple raw buffers for more -//or handle 16bit values for page size - +//max raw buffer size is only limited based on buffer struct //raw buffer memory to which smaller buffers will be created from //set pointers and lengths to prevent buffer conflicts -//static uint8_t raw_buffer[NUM_RAW_BANKS * RAW_BANK_SIZE]; //8 banks of 32bytes each 256Bytes total -static uint8_t raw_buffer[256]; //8 banks of 32bytes each 256Bytes total +static uint8_t raw_buffer[NUM_RAW_BANKS * RAW_BANK_SIZE]; //8 banks of 32bytes each 256Bytes total //buffer status stores allocation status of each raw buffer 32Byte bank -//static uint8_t raw_bank_status[NUM_RAW_BANKS]; -static uint8_t raw_bank_status[8]; +static uint8_t raw_bank_status[NUM_RAW_BANKS]; + +//min define of two buffers +static buffer buff0; +static buffer buff1; +#if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) +static buffer buff2; +static buffer buff3; +#endif +#ifdef NUM_BUFFERS_8 +static buffer buff4; +static buffer buff5; +static buffer buff6; +static buffer buff7; +#endif + + +/* Desc:Bridge between usb.c and buffer.c functions + * usb.c calls this function providing setup packet info + * usb.c also provides pointer to small 'rv' return value buffer of 8bytes + * and pointer to rlen so buffer.c can decide wether to utilize the + * small 8byte generic return buffer or point usbMsgPtr to some larger buffer of sram. + * this function interprets opcode type to call proper opcode switch function + * Pre: opcode must be defined in shared_dict_buffer.h + * Post:function call complete. + * rlen updated to lenght of return data + * rv[0] contains SUCCESS/ERROR code + * rv buffer filled with return data for small data requests + * Rtn: pointer to ram buffer to be returned over USB + */ +uint8_t * buffer_usb_call( setup_packet *spacket, uint8_t *rv, uint16_t *rlen) +{ + buffer *called_buff = &buff0; //used to point to buffer that was called based on opcode + uint8_t *rptr = rv; //used for return pointer set to small rv buffer by default + + switch (spacket->opcode) { + + //opcodes which don't address a specific buffer object + case BUFF_OPCODE_NRV_MIN ... BUFF_OPCODE_NRV_MAX: + rv[RV_ERR_IDX] = buffer_opcode_no_return( spacket->opcode, NULL, + spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); + *rlen = 1; + break; + + case BUFF_OPCODE_RV_MIN ... BUFF_OPCODE_RV_MAX: + rv[RV_ERR_IDX] = buffer_opcode_return( spacket->opcode, NULL, + spacket->operandMSB, spacket->operandLSB, spacket->miscdata, &rv[1] ); + *rlen = 2; + break; + + //opcodes which include designation of which buffer is being called in lower bits + case BUFF_OPCODE_BUFN_MIN ... BUFF_OPCODE_BUFN_MAX: + //mask out last three bits to detect buffer being called based on opcode number + switch ( (spacket->opcode) & 0x07) { + //2 buffers minimum support + case 0: called_buff = &buff0; break; + case 1: called_buff = &buff1; break; +# if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) + //4-8 buffers + case 2: called_buff = &buff2; break; + case 3: called_buff = &buff3; break; +# endif +# ifdef NUM_BUFFERS_8 + //8 buffers + case 4: called_buff = &buff4; break; + case 5: called_buff = &buff5; break; + case 6: called_buff = &buff6; break; + case 7: called_buff = &buff7; break; +# endif + default: //opcode sent for non-existent buffer + rv[RV_ERR_IDX] = ERR_BUFN_DOES_NOT_EXIST; + } + //now that we have pointer to buffer object call associated function + switch ( spacket->opcode ) { + case BUFF_OPCODE_BUFN_NRV_MIN ... BUFF_OPCODE_BUFN_NRV_MAX: + rv[RV_ERR_IDX] = buffer_opcode_buffnum_no_return( spacket->opcode, called_buff, + spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); + break; + case BUFF_OPCODE_BUFN_RV_MIN ... BUFF_OPCODE_BUFN_RV_MAX: + //returnlength = somereturn value( spacket->opcode, &called_buff, + //spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); + //return pointer to buffer's data + rptr = called_buff->data; + break; + } + break; + + default: //nes opcode min/max definition error + rv[RV_ERR_IDX] = ERR_BAD_BUFF_OP_MINMAX; + } + + return rptr; +} + /* Desc:Function takes an opcode which was transmitted via USB @@ -51,8 +116,28 @@ uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, ui case RAW_BUFFER_RESET: raw_buffer_reset(); break; - case ALLOCATE_BUFFER0 ... ALLOCATE_BUFFER7: - allocate_buffer( &(*buff), oper1, oper2, oper3 ); + default: + //opcode doesn't exist + return ERR_UNKN_BUFF_OPCODE_NRV; + } + + return SUCCESS; + +} + +/* Desc:Function takes an opcode which was transmitted via USB + * then decodes it to call designated function. + * shared_dict_buffer.h is used in both host and fw to ensure opcodes/names align + * Pre: Macros must be defined in firmware pinport.h + * opcode must be defined in shared_dict_buffer.h + * Post:function call complete. + * Rtn: SUCCESS if opcode found, ERR_UNKN_BUFF_OPCODE_NRV if opcode not present. + */ +uint8_t buffer_opcode_return( uint8_t opcode, buffer *buff, uint8_t operMSB, uint8_t operLSB, uint8_t miscdata, uint8_t *rvalue ) +{ + switch (opcode) { + case RAW_BANK_STATUS: + *rvalue = raw_bank_status[operLSB]; break; default: //opcode doesn't exist @@ -63,9 +148,34 @@ uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, ui } +/* Desc:Function takes an opcode which was transmitted via USB + * then decodes it to call designated function. + * shared_dict_buffer.h is used in both host and fw to ensure opcodes/names align + * This function is for opcodes which use their opcode lower bits to + * denote which buffer to be operated on. + * Pre: Macros must be defined in firmware pinport.h + * opcode must be defined in shared_dict_buffer.h + * Post:function call complete. + * Rtn: SUCCESS if opcode found, ERR_UNKN_BUFF_OPCODE_BUFN_NRV if opcode not present. + */ +uint8_t buffer_opcode_buffnum_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ) +{ + switch (opcode) { + case ALLOCATE_BUFFER0 ... ALLOCATE_BUFFER7: + return allocate_buffer( buff, oper1, oper2, oper3 ); + break; + default: + //opcode doesn't exist + return ERR_UNKN_BUFF_OPCODE_BUFN_NRV; + } + + return SUCCESS; + +} + /* Desc:Blindly resets all buffer allocation and values * Host instructs this to be called. - * Pre: static instantitions of raw_buffer, raw_bank_status, and buff0-7 above + * Pre: static instantitions of raw_buffer, raw_bank_status, and buff0-7 * Post:all raw buffer ram unallocated * buffer status updated to UNALLOC * Rtn: None @@ -80,23 +190,29 @@ void raw_buffer_reset( ) } //unallocate all buffer objects + //set buffer id to UNALLOC +//min 2 buffers buff0.status = UNALLOC; buff1.status = UNALLOC; + buff0.id = UNALLOC; + buff1.id = UNALLOC; +// 4-8 buffers +#if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) buff2.status = UNALLOC; buff3.status = UNALLOC; + buff2.id = UNALLOC; + buff3.id = UNALLOC; +#endif //8 buffers +#ifdef NUM_BUFFERS_8 buff4.status = UNALLOC; buff5.status = UNALLOC; buff6.status = UNALLOC; buff7.status = UNALLOC; - //set buffer id to UNALLOC - buff0.id = UNALLOC; - buff1.id = UNALLOC; - buff2.id = UNALLOC; - buff3.id = UNALLOC; buff4.id = UNALLOC; buff5.id = UNALLOC; buff6.id = UNALLOC; buff7.id = UNALLOC; +#endif } @@ -110,6 +226,8 @@ void raw_buffer_reset( ) * another buffer or bank already allocated. * pass in pointer to buffer object to be allocated * pass base bank number and number of banks in buffer + * This function works with various sizes of raw buffer + * as it works based on NUM_RAW_BANKS and RAW_BANK_SIZE * Pre: static instantitions of raw_buffer raw_bank_status, * and buff0-7 above. * Buffer must be unallocated. @@ -122,7 +240,6 @@ void raw_buffer_reset( ) * all other buffer values cleared to zero * Rtn: SUCCESS or ERROR code if unable to allocate */ -//uint8_t allocate_buffer( struct buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_t num_banks ) uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_t num_banks ) { uint8_t i; @@ -132,6 +249,10 @@ uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_ //trying to allocate SRAM past end of raw_buffer return ERR_BUFF_ALLOC_RANGE; } + if ( (num_banks) == 0 ) { + //trying to allocate buffer with zero banks + return ERR_BUFF_ALLOC_RANGE; + } //check that buffer isn't already allocated if ( buff->status != UNALLOC) { @@ -151,7 +272,9 @@ uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_ //seems that buffer and raw are free allocate them as requested buff->id = new_id; buff->status = EMPTY; - buff->data = &raw_buffer[base_bank]; + + //set buffer data pointer to base ram address + buff->data = &raw_buffer[base_bank*RAW_BANK_SIZE]; //set bank status to bank's id for ( i=0; i - - -//~16 bytes per buffer... -typedef struct buffer { - uint8_t *data; //pointer to base buffer's allocated sram - uint8_t size; //size of buffer in bytes (max 256 bytes) - uint8_t status; //current status of buffer USB load/unload, flashing, waiting, erase - uint8_t cur_byte; //byte currently being loaded/unloaded/flashed/read - uint8_t reload; //add this number to page_num for next loading - uint8_t id; //address bits between buffer size and page number - //ie need 2x128 byte buffers making buff_num = A7 - //ie need 4x64 byte buffers making buff_num = A7:6 - //ie need 8x32 byte buffers making buff_num = A7:5 - uint16_t page_num; //address bits beyond buffer's size and buff_num A23-A8 - //MSB A23-16, LSB A15-8 - uint8_t mem_type; //SNES ROM, SNES RAM, PRG ROM, PRG RAM, CHR ROM, CHR RAM, CPLD, SPI - uint8_t part_num; //used to define unlock commands, sector erase, etc - uint8_t multiple; //number of times to program this page - uint8_t add_mult; //add this number to page_num for multiple programs - //CHR shift LSb to A13 (max 2MByte) - //PRG shift LSb to A14 (max 4MByte) - //SNES add to MSB of page_num (max 16MByte) - uint8_t mapper; //mapper number of board - uint8_t mapvar; //mapper variant - uint8_t function; //function "pointer" for flash/dump operation control -}buffer; - -static buffer buff0; -static buffer buff1; -static buffer buff2; -static buffer buff3; -static buffer buff4; -static buffer buff5; -static buffer buff6; -static buffer buff7; - +#include "types.h" #include "logic.h" +#include "usb.h" #include "shared_dictionaries.h" #include "shared_errors.h" + +uint8_t * buffer_usb_call( setup_packet *spacket, uint8_t *rv, uint16_t *rlen); uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ); +uint8_t buffer_opcode_buffnum_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ); +uint8_t buffer_opcode_return( uint8_t opcode, buffer *buff, uint8_t operMSB, uint8_t operLSB, uint8_t miscdata, uint8_t *rvalue ); void raw_buffer_reset( ); uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_t num_banks ); diff --git a/firmware/source/types.h b/firmware/source/types.h new file mode 100644 index 0000000..a0bd294 --- /dev/null +++ b/firmware/source/types.h @@ -0,0 +1,39 @@ +#ifndef _types_h +#define _types_h + +typedef struct setup_packet{ + uint8_t bmRequestType; //contains endpoint + uint8_t bRequest; //designates dictionary of opcode + uint8_t opcode; //wValueLSB (little endian) + uint8_t miscdata; //wValueMSB + uint8_t operandLSB; //wIndexLSB + uint8_t operandMSB; //wIndexMSB + uint16_t wLength; +}setup_packet; + +//~16 bytes per buffer... +typedef struct buffer { + uint8_t *data; //pointer to base buffer's allocated sram + uint8_t size; //size of buffer in bytes (max 256 bytes) + uint8_t status; //current status of buffer USB load/unload, flashing, waiting, erase + uint8_t cur_byte; //byte currently being loaded/unloaded/flashed/read + uint8_t reload; //add this number to page_num for next loading + uint8_t id; //address bits between buffer size and page number + //ie need 2x128 byte buffers making buff_num = A7 + //ie need 4x64 byte buffers making buff_num = A7:6 + //ie need 8x32 byte buffers making buff_num = A7:5 + uint16_t page_num; //address bits beyond buffer's size and buff_num A23-A8 + //MSB A23-16, LSB A15-8 + uint8_t mem_type; //SNES ROM, SNES RAM, PRG ROM, PRG RAM, CHR ROM, CHR RAM, CPLD, SPI + uint8_t part_num; //used to define unlock commands, sector erase, etc + uint8_t multiple; //number of times to program this page + uint8_t add_mult; //add this number to page_num for multiple programs + //CHR shift LSb to A13 (max 2MByte) + //PRG shift LSb to A14 (max 4MByte) + //SNES add to MSB of page_num (max 16MByte) + uint8_t mapper; //mapper number of board + uint8_t mapvar; //mapper variant + uint8_t function; //function "pointer" for flash/dump operation control +}buffer; + +#endif diff --git a/firmware/source/usb.c b/firmware/source/usb.c index 19cc1e9..f466d5e 100644 --- a/firmware/source/usb.c +++ b/firmware/source/usb.c @@ -38,34 +38,43 @@ // usbWord_t wLength; //}usbRequest_t; -#define ENDPOINT_BIT 0x80 //Bit 7 of bmRequest type determines endpoint -#define ENDPOINT_IN 0x80 //In: device-to-host. -#define ENDPOINT_OUT 0x00 //Out: host-to-device. -typedef struct setup_packet{ - uint8_t bmRequestType; //contains endpoint - uint8_t bRequest; //designates dictionary of opcode - uint8_t opcode; //wValueLSB (little endian) - uint8_t miscdata; //wValueMSB - uint8_t operandLSB; //wIndexLSB - uint8_t operandMSB; //wIndexMSB - uint16_t wLength; -}setup_packet; - USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { //cast incoming data into the the usb setup packet it is setup_packet *spacket = (void *)data; //8 Byte buffer to be used for returning error code and return values - //must be static so driver can still access after function return - static uchar rv[8]; - //rv[0] contains opcode success/error code + //must be static so V-USB driver can still access after function return + static uint8_t rv[RETURN_BUFF_SIZE]; + //rv[RV_ERR_IDX] contains opcode success/error code //rv[1-7] available for return data, start with index 1 + //rv[RETURN_BUFF_FIRST_IDX-RETURN_BUFFER_LAST_IDX] - //number of bytes to return to host - uint8_t rlen = 0; + /* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data + * block and return the length of the data in 'usbFunctionSetup()'. The driver + * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The + * driver will then call 'usbFunctionRead()' when data is needed. See the + */ + //by default want to return some portion of the 8 byte rv "return value" + //buffer. If no return data requested from host rlen = 0, so this wouldn't matter + //Some dictionaries/opcodes that want to return larger buffers though + //this function will set usbMsgPtr to point to that larger buffer when supported + //avr-gcc doesn't like this and gives warning + //source/usb.c:64: warning: assignment makes integer from pointer without a cast + //tried casting it to usbMsgPtr + usbMsgPtr = (usbMsgPtr_t)rv; + +//#if USB_CFG_LONG_TRANSFERS +// //number of bytes to return to host +// //16bit meets max possible 16KBytes with V-USB long transfers enabled + uint16_t rlen = 0; //just go ahead and set to 16bit to be safe + //prob not worth saving a measly byte.. +//#else +// //8bit is enough for 254 bit non-long xfrs +// uint8_t rlen = 0; +//#endif //determine endpoint IN/OUT if ( (spacket->bmRequestType & ENDPOINT_BIT) == ENDPOINT_IN ) { @@ -85,131 +94,92 @@ USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { case PINPORT: switch (spacket->opcode) { case PP_OPCODE_ONLY_MIN ... PP_OPCODE_ONLY_MAX: - rv[0] = pinport_opcode_only( spacket->opcode ); + rv[RV_ERR_IDX] = pinport_opcode_only( spacket->opcode ); break; case PP_OPCODE_8BOP_MIN ... PP_OPCODE_8BOP_MAX: - rv[0] = pinport_opcode_8b_operand( + rv[RV_ERR_IDX] = pinport_opcode_8b_operand( spacket->opcode, spacket->operandLSB ); break; case PP_OPCODE_16BOP_MIN ... PP_OPCODE_16BOP_MAX: - rv[0] = pinport_opcode_16b_operand( + rv[RV_ERR_IDX] = pinport_opcode_16b_operand( spacket->opcode, spacket->operandMSB, spacket->operandLSB ); break; case PP_OPCODE_24BOP_MIN ... PP_OPCODE_24BOP_MAX: - rv[0] = pinport_opcode_24b_operand( spacket->opcode, + rv[RV_ERR_IDX] = pinport_opcode_24b_operand( spacket->opcode, spacket->miscdata, spacket->operandMSB, spacket->operandLSB ); break; case PP_OPCODE_8BRV_MIN ... PP_OPCODE_8BRV_MAX: - rv[0] = pinport_opcode_8b_return( spacket->opcode, &rv[1]); + rv[RV_ERR_IDX] = pinport_opcode_8b_return( spacket->opcode, &rv[RV_DATA0_IDX]); rlen ++; break; default: //pinport opcode min/max definition error - rv[0] = ERR_BAD_PP_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_PP_OP_MINMAX; } break; //end of PINPORT case IO: switch (spacket->opcode) { case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX: - rv[0] = io_opcode_only( spacket->opcode ); + rv[RV_ERR_IDX] = io_opcode_only( spacket->opcode ); break; case IO_OPCODE_RTN_MIN ... IO_OPCODE_RTN_MAX: - rv[0] = io_opcode_return( - spacket->opcode, &rv[1] ); + rv[RV_ERR_IDX] = io_opcode_return( + spacket->opcode, &rv[RV_DATA0_IDX] ); rlen = 8; break; default: //io opcode min/max definition error - rv[0] = ERR_BAD_IO_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_IO_OP_MINMAX; } break; //end of IO case NES: switch (spacket->opcode) { case NES_OPCODE_24BOP_MIN ... NES_OPCODE_24BOP_MAX: - rv[0] = nes_opcode_24b_operand( spacket->opcode, + rv[RV_ERR_IDX] = nes_opcode_24b_operand( spacket->opcode, spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); break; case NES_OPCODE_16BOP_8BRV_MIN ... NES_OPCODE_16BOP_8BRV_MAX: - rv[0] = nes_opcode_16b_operand_8b_return( spacket->opcode, - spacket->operandMSB, spacket->operandLSB, &rv[1]); + rv[RV_ERR_IDX] = nes_opcode_16b_operand_8b_return( spacket->opcode, + spacket->operandMSB, spacket->operandLSB, &rv[RV_DATA0_IDX]); rlen++; break; default: //nes opcode min/max definition error - rv[0] = ERR_BAD_NES_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_NES_OP_MINMAX; } break; //end of NES case SNES: switch (spacket->opcode) { case SNES_OPCODE_24BOP_MIN ... SNES_OPCODE_24BOP_MAX: - rv[0] = snes_opcode_24b_operand( spacket->opcode, + rv[RV_ERR_IDX] = snes_opcode_24b_operand( spacket->opcode, spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); break; case SNES_OPCODE_24BOP_8BRV_MIN ... SNES_OPCODE_24BOP_8BRV_MAX: - rv[0] = snes_opcode_24b_operand_8b_return( spacket->opcode, - spacket->miscdata, spacket->operandMSB, spacket->operandLSB, &rv[1]); + rv[RV_ERR_IDX] = snes_opcode_24b_operand_8b_return( spacket->opcode, + spacket->miscdata, spacket->operandMSB, spacket->operandLSB, &rv[RV_DATA0_IDX]); rlen++; break; default: //snes opcode min/max definition error - rv[0] = ERR_BAD_SNES_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_SNES_OP_MINMAX; } break; //end of SNES case BUFFER: - switch (spacket->opcode) { - case BUFF_OPCODE_NRV_MIN ... BUFF_OPCODE_NRV_MAX: - rv[0] = buffer_opcode_no_return( spacket->opcode, NULL, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - break; - case BUFF_OPCODE_BUFn_NRV_MIN ... BUFF_OPCODE_BUFn_NRV_MAX: - switch ( (spacket->opcode) & 0x07) { - case 0: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff0, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 1: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff1, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 2: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff2, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 3: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff3, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 4: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff4, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 5: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff5, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 6: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff6, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 7: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff7, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - default: //nes opcode min/max definition error - rv[0] = ERR_BAD_BUFF_OP_MINMAX; - } - break; - default: //nes opcode min/max definition error - rv[0] = ERR_BAD_BUFF_OP_MINMAX; - } + //just give buffer.c the setup packet and let it figure things out for itself + usbMsgPtr = (usbMsgPtr_t)buffer_usb_call( spacket, rv, &rlen ); break; //end of BUFFER default: //request (aka dictionary) is unknown - rv[0] = ERR_UNKN_DICTIONARY; + rv[RV_ERR_IDX] = ERR_UNKN_DICTIONARY; } - /* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data - * block and return the length of the data in 'usbFunctionSetup()'. The driver - * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The - * driver will then call 'usbFunctionRead()' when data is needed. See the - */ - usbMsgPtr = rv; + //TODO add check that verifies rlen == setup packet return lenght request + //current state has error checking somewhat embeded in the fact the host + //will detect when return length differs from requested return rlen; - //return USB_NO_MSG; + //return USB_NO_MSG; //if want usbFunctionRead called during IN token data packets //Don't have a use for usbFunctionRead yet.. Not expecting to anytime soon //probably easier and perhaps faster to send cart dump commands and store rom image //in a buffer to be returned here. diff --git a/firmware/source/usb.h b/firmware/source/usb.h index d21a285..b8fa0b1 100644 --- a/firmware/source/usb.h +++ b/firmware/source/usb.h @@ -5,6 +5,7 @@ #include "usbdrv.h" #include "logic.h" +#include "types.h" #include "shared_dictionaries.h" #include "shared_errors.h" #include "pinport.h" @@ -13,5 +14,15 @@ #include "snes.h" #include "buffer.h" +#define ENDPOINT_BIT 0x80 //Bit 7 of bmRequest type determines endpoint +#define ENDPOINT_IN 0x80 //In: device-to-host. +#define ENDPOINT_OUT 0x00 //Out: host-to-device. + + +//TODO these should probably be in shared so host code and utilize them on the other side +#define RETURN_BUFF_SIZE 8 //number of bytes in generic return buffer +#define RV_ERR_IDX 0 //(first) index of buffer that contains SUCCESS/ERROR# +#define RV_DATA0_IDX RV_ERR_IDX + 1 //first index of return data +#define RV_DATA_MAX_IDX RETURN_BUFF_SIZE - 1 //last index available for return data #endif diff --git a/host/source/dictionary.c b/host/source/dictionary.c index 0389177..d38296f 100644 --- a/host/source/dictionary.c +++ b/host/source/dictionary.c @@ -40,7 +40,7 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, transfer->data = rbuf; - debug("dictionary call dict:%d opcode:%d/%x addr:%x data:%x", dictionary, opcode, opcode, addr, miscdata); + debug("\ndictionary call dict:%d opcode:%d/%x addr:%x data:%x", dictionary, opcode, opcode, addr, miscdata); switch (dictionary) { case PINPORT: debug("dict: PINPORT"); transfer->wLength = 1; @@ -111,6 +111,28 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, } break; //end of SNES + case BUFFER: debug("dict: BUFFER"); + transfer->wLength = 1; + switch (opcode) { + case BUFF_OPCODE_NRV_MIN ... BUFF_OPCODE_NRV_MAX: + debug("BUFF_OPCODE_NRV"); + break; + case BUFF_OPCODE_RV_MIN ... BUFF_OPCODE_RV_MAX: + debug("BUFF_OPCODE_RV"); + transfer->wLength = 2; + break; + case BUFF_OPCODE_BUFN_NRV_MIN ... BUFF_OPCODE_BUFN_NRV_MAX: + debug("BUFF_OPCODE_NRV"); + break; + case BUFF_OPCODE_BUFN_RV_MIN ... BUFF_OPCODE_BUFN_RV_MAX: + debug("BUFF_OPCODE_RV"); + //TODO + break; + default: //snes opcode min/max definition error + sentinel("bad BUFFER opcode min/max err:%d",ERR_BAD_BUFF_OP_MINMAX); + } + break; //end of BUFF + default: //request (aka dictionary) is unknown sentinel("unknown DICT err:%d",ERR_UNKN_DICTIONARY); @@ -120,7 +142,12 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, int xfr_cnt; xfr_cnt = usb_transfer( transfer ); - debug("xf: %d er: %d rv: %x, %x, %x, %x, %x, %x, %x",xfr_cnt, rbuf[0], rbuf[1], rbuf[2], rbuf[3], rbuf[4], rbuf[5], rbuf[6], rbuf[7]); + printf(" xf: %d er: %d rv:",xfr_cnt, rbuf[0]); + int i ; + for (i=1; i