firmware buffer.c reorganization and some intitial testing complete.

moved all buffer operations out of usb.c with new bridge function between
the two files.  Lots of pointing going on and lessons learned..
Thankfully everything seems to be working if you actually call the
functions as I designed them..  Gotta love trouble shooting bugs that
don't exist..  Helped updating allocate output to get returned as error
back to the host.

Moved typedef structs to firmware type.h file as seemed to cause
compilation issues being contained in the files .h file when other .c
files needed those types.

Fixed casting warnings with usbMsgPtr ended up looking at usbdrv.c figured
out how close I got, just shouldn't have been putting the * in there..
This commit is contained in:
Paul Molloy 2016-11-28 22:16:35 -06:00
parent 52ef11c7e3
commit 80943f7f62
9 changed files with 399 additions and 190 deletions

View File

@ -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<num_banks; i++) {
@ -161,8 +284,3 @@ uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_
return SUCCESS;
}

View File

@ -2,47 +2,17 @@
#define _buffer_h
#include <avr/io.h>
//~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 );

39
firmware/source/types.h Normal file
View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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<xfr_cnt; i++){
printf(" %x,", rbuf[i]);
}
printf("\n");
check(rbuf[0] == SUCCESS, "retro programmer had error: %d, dict:%d, opcode:%d/%x, addr:%x, data:%x",rbuf[0], dictionary, opcode, opcode, addr, miscdata)
//send command

View File

@ -6,16 +6,51 @@ int erase_nes( USBtransfer *transfer )
debug("erasing");
//dict opcode addr data
dictionary_call( transfer, IO, IO_RESET, 0, 0);
dictionary_call( transfer, IO, NES_INIT, 0, 0);
dictionary_call( transfer, IO, EXP0_PULLUP_TEST, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 0, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 1, 0);
debug("reset");
dictionary_call( transfer, BUFFER, RAW_BUFFER_RESET, 0, 0);
debug("read status");
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 0, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 1, 0);
debug("allocate 0");
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER0, 0x1A00, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER1, 0x2A01, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER2, 0x3A02, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER3, 0x4A03, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER4, 0x5A04, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER5, 0x6A05, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER6, 0x7A06, 1);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER7, 0x8A07, 1);
debug("read status");
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 0, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 1, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 2, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 3, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 4, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 5, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 6, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 7, 0);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER7, 0x8A07, 1);
debug("reset");
dictionary_call( transfer, BUFFER, RAW_BUFFER_RESET, 0, 0);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 7, 0);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER7, 0x8A07, 1);
dictionary_call( transfer, BUFFER, RAW_BANK_STATUS, 7, 0);
dictionary_call( transfer, BUFFER, ALLOCATE_BUFFER7, 0x5A05, 1);
//dictionary_call( transfer, IO, IO_RESET, 0, 0);
//dictionary_call( transfer, IO, NES_INIT, 0, 0);
//dictionary_call( transfer, IO, EXP0_PULLUP_TEST, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
////software mode
// dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0xAA);

View File

@ -15,21 +15,44 @@
//
//=============================================================================================
//=============================================================================================
//raw buffer banks & size
#define NUM_RAW_BANKS 8
#define RAW_BANK_SIZE 32 //in bytes
//This determines the raw buffer sram space on avr at firmware compile time
//one byte per bank is instantiated to keep track of that banks' allocation status
//a buffer must be as large as one bank, but a buffer can consume multiple banks
//only limit to buffer size is the buffer structure
//current buffer structure utilizes a single byte for current byte counter
//which limits to 256 bytes per buffer currently
//having 16bit value support would expand this, or somehow shifting current byte
//to account for multiple bytes could expand further
#define NUM_RAW_BANKS 8 // 8*32 = 256 bytes of buffer
//#define NUM_RAW_BANKS 16 //16*32 = 512 bytes of buffer
#define RAW_BANK_SIZE 32 //bank size in bytes
//number of buffer objects
//This controls number of static buffer objects instantiated in firmware at compile time
//note this also controls opcodes created/supported by firmware
//reducing number of buffers frees firmware sram by ~16bytes per buffer object
//not much reason to have less than 2 atleast allow double buffering
//so one can be getting loaded/unloaded by USB while other is dumping/flashing
//current max is 8, but only really limited by opcode definitions to address all buffers
//makes #ifdef code simpler to only allow buffer numbers that are power of 2
//#define NUM_BUFFERS_2 2
//#define NUM_BUFFERS_4 4
#define NUM_BUFFERS_8 8
//defined here so identical to host and firmware
//status values
#define EMPTY 0x00
//#define ERROR 0x10
//#define USB_UNLOADING 0x80
//#define USB_LOADING 0x90
//#define CHECKING 0xC0
//#define DUMPING 0xD0
//#define ERASING 0xE0
//#define FLASHING 0xF0
//#define FLASH_WAIT 0xF8
#define PROBLEM 0x10
#define USB_UNLOADING 0x80
#define USB_LOADING 0x90
#define CHECKING 0xC0
#define DUMPING 0xD0
#define ERASING 0xE0
#define FLASHING 0xF0
#define FLASH_WAIT 0xF8
#define UNALLOC 0xFF
@ -40,8 +63,10 @@
//=============================================================================================
// Detect this opcode/operand setup with opcode between the following defines:
#define BUFF_OPCODE_NRV_MIN 0x00
#define BUFF_OPCODE_NRV_MAX 0x7F
#define BUFF_OPCODE_NRV_MAX 0x3F
//
#define BUFF_OPCODE_RV_MIN 0x40
#define BUFF_OPCODE_RV_MAX 0x7F
//=============================================================================================
//=============================================================================================
@ -49,15 +74,25 @@
//reset all buffers to unallocated
#define RAW_BUFFER_RESET 0x00
//send bank number and read back it's status
//0xFF-UNALLOC
//gets assigned buffer ID number when allocated
#define RAW_BANK_STATUS 0x40
//=============================================================================================
// OPCODES with up to 24bit operand and no return value besides SUCCESS/ERROR_CODE
// BUFFER NUMBER denoted in lower nibble of opcode
//=============================================================================================
// Detect this opcode/operand setup with opcode between the following defines:
#define BUFF_OPCODE_BUFn_NRV_MIN 0x80
#define BUFF_OPCODE_BUFn_NRV_MAX 0xFF
// Detect this opcode group which uses 3 LSbits to determine which buffer to call
#define BUFF_OPCODE_BUFN_MIN 0x80
#define BUFF_OPCODE_BUFN_MAX 0xFF
//
// Detect this opcode/operand setup with opcode between the following defines:
#define BUFF_OPCODE_BUFN_NRV_MIN 0x80
#define BUFF_OPCODE_BUFN_NRV_MAX 0xBF
//
#define BUFF_OPCODE_BUFN_RV_MIN 0xC0
#define BUFF_OPCODE_BUFN_RV_MAX 0xFF
//=============================================================================================
//=============================================================================================
//allocate firmware sram to a buffer

View File

@ -10,6 +10,7 @@
#define ERR_BAD_NES_OP_MINMAX 131
#define ERR_BAD_SNES_OP_MINMAX 132
#define ERR_BAD_BUFF_OP_MINMAX 133
#define ERR_BUFN_DOES_NOT_EXIST 134
#define ERR_UNKN_PP_OPCODE_ONLY 140
@ -28,11 +29,14 @@
#define ERR_UNKN_SNES_OPCODE_24BOP_8BRV 171
#define ERR_UNKN_BUFF_OPCODE_NRV 180
#define ERR_UNKN_BUFF_OPCODE_RV 181
#define ERR_UNKN_BUFF_OPCODE_BUFN_NRV 182
#define ERR_BUFF_ALLOC_RANGE 190
#define ERR_BUFF_STATUS_ALREADY_ALLOC 191
#define ERR_BUFF_ID_ALREADY_ALLOC 192
#define ERR_BUFF_RAW_ALREADY_ALLOC 193
#define ERR_BUFF_ALLOC_SIZE_ZERO 194
//max error number 255