I have ported my old project “pNesX” game console emulator to the nucleo.
Dependencies: SDFileSystem mbed
Intro
I have ported my old project “pNesX” to the STM32 Nucleo. The pNesX is a NES emulator for the PlayStation that I have created 16 years ago!
Emulation part was almost without change, the sound part was newly added.
Parts
STM32 Nucleo F446RE |
QVGA 2.2 TFT SPI (with the SD card slot) |
Audio jack(TS or TRS) |
USB Connector |
Register 100k, 10k, 4.7k, 100 |
Capacitor 0.01uF, 2.2uF |
Breadboard |
Wires |
Computer Speakers |
USB GamePad |
Wiring diagram
TFT J2 | Nucleo |
---|---|
VCC | 3V3 |
GND | GND |
CS | PB_5(D4) |
Reset | PA_10(D2) Pull Up(100k) |
D/C | PA_8(D7) |
MOSI | PA_7(D11) |
SCK | PA_5(D13) |
LED | LED-100ohm-3V3 |
MISO | PA_6(D12) |
TFT J4 | Nucleo |
---|---|
SD_CS | PA_9 |
SD_MOSI | PB_15 |
SD_MISO | PB_14 |
SD_SCK | PB_13 |
Audio | Nucleo |
---|---|
TIP | PA_4(A2) |
USB con. | Nucleo |
---|---|
GND | GND |
+ | PA_12 |
- | PA_11 |
5V | 5V |
Limitations
- Since the rest of the RAM is about 50kbyte, maximum capacity of the game ROM is about 50kbyte.
- The length of the file name up to 32 characters.
- The number of files in the folder is up to 100.
Used Library
- SDFileSystem by Neil Thiessen
- F401RE-USBHost by Norimasa Okamoto
- USBHostGamepad by Yuuichi Akagawa
Revision 0:3dac1f1bc9e0, committed 2016-04-03
- Comitter:
- beaglescout007
- Date:
- Sun Apr 03 07:45:29 2016 +0000
- Commit message:
- Release
Changed in this revision
diff -r 000000000000 -r 3dac1f1bc9e0 K6502.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/K6502.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,1058 @@ +/*===================================================================*/ +/* */ +/* K6502.cpp : 6502 Emulator */ +/* */ +/* 1999/10/19 Racoon New preparation */ +/* */ +/*===================================================================*/ + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ +#include "K6502.h" + +/*-------------------------------------------------------------------*/ +/* Operation Macros */ +/*-------------------------------------------------------------------*/ + +// Clock Op. +#define CLK(a) g_wPassedClocks += (a); + +// Addressing Op. +// Address +// (Indirect,X) +#define AA_IX K6502_ReadZpW( K6502_Read( PC++ ) + X ) +// (Indirect),Y +#define AA_IY K6502_ReadZpW( K6502_Read( PC++ ) ) + Y +// Zero Page +#define AA_ZP K6502_Read( PC++ ) +// Zero Page,X +#define AA_ZPX (BYTE)( K6502_Read( PC++ ) + X ) +// Zero Page,Y +#define AA_ZPY (BYTE)( K6502_Read( PC++ ) + Y ) +// Absolute +#define AA_ABS ( K6502_Read( PC++ ) | (WORD)K6502_Read( PC++ ) << 8 ) +// Absolute2 ( PC-- ) +#define AA_ABS2 ( K6502_Read( PC++ ) | (WORD)K6502_Read( PC ) << 8 ) +// Absolute,X +#define AA_ABSX AA_ABS + X +// Absolute,Y +#define AA_ABSY AA_ABS + Y + +// Data +// (Indirect,X) +#define A_IX K6502_Read( AA_IX ) +// (Indirect),Y +#define A_IY K6502_ReadIY() +// Zero Page +#define A_ZP K6502_ReadZp( AA_ZP ) +// Zero Page,X +#define A_ZPX K6502_ReadZp( AA_ZPX ) +// Zero Page,Y +#define A_ZPY K6502_ReadZp( AA_ZPY ) +// Absolute +#define A_ABS K6502_Read( AA_ABS ) +// Absolute,X +#define A_ABSX K6502_ReadAbsX() +// Absolute,Y +#define A_ABSY K6502_ReadAbsY() +// Immediate +#define A_IMM K6502_Read( PC++ ) + +// Flag Op. +#define SETF(a) F |= (a) +#define RSTF(a) F &= ~(a) +#define TEST(a) RSTF( FLAG_N | FLAG_Z ); SETF( g_byTestTable[ a ] ) + +// Load & Store Op. +#define STA(a) K6502_Write( (a), A ); +#define STX(a) K6502_Write( (a), X ); +#define STY(a) K6502_Write( (a), Y ); +#define LDA(a) A = (a); TEST( A ); +#define LDX(a) X = (a); TEST( X ); +#define LDY(a) Y = (a); TEST( Y ); + +// Stack Op. +#define PUSH(a) K6502_Write( BASE_STACK + SP--, (a) ) +#define PUSHW(a) PUSH( (a) >> 8 ); PUSH( (a) & 0xff ) +#define POP(a) a = K6502_Read( BASE_STACK + ++SP ) +#define POPW(a) POP(a); a |= ( K6502_Read( BASE_STACK + ++SP ) << 8 ) + +// Logical Op. +#define ORA(a) A |= (a); TEST( A ) +#define AND(a) A &= (a); TEST( A ) +#define EOR(a) A ^= (a); TEST( A ) +#define BIT(a) byD0 = (a); RSTF( FLAG_N | FLAG_V | FLAG_Z ); SETF( ( byD0 & ( FLAG_N | FLAG_V ) ) | ( ( byD0 & A ) ? 0 : FLAG_Z ) ); +#define CMP(a) wD0 = (WORD)A - (a); RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_byTestTable[ wD0 & 0xff ] | ( wD0 < 0x100 ? FLAG_C : 0 ) ); +#define CPX(a) wD0 = (WORD)X - (a); RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_byTestTable[ wD0 & 0xff ] | ( wD0 < 0x100 ? FLAG_C : 0 ) ); +#define CPY(a) wD0 = (WORD)Y - (a); RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_byTestTable[ wD0 & 0xff ] | ( wD0 < 0x100 ? FLAG_C : 0 ) ); + +// Math Op. (A D flag isn't being supported.) +#define ADC(a) byD0 = (a); \ + wD0 = A + byD0 + ( F & FLAG_C ); \ + byD1 = (BYTE)wD0; \ + RSTF( FLAG_N | FLAG_V | FLAG_Z | FLAG_C ); \ + SETF( g_byTestTable[ byD1 ] | ( ( ~( A ^ byD0 ) & ( A ^ byD1 ) & 0x80 ) ? FLAG_V : 0 ) | ( wD0 > 0xff ) ); \ + A = byD1; + +#define SBC(a) byD0 = (a); \ + wD0 = A - byD0 - ( ~F & FLAG_C ); \ + byD1 = (BYTE)wD0; \ + RSTF( FLAG_N | FLAG_V | FLAG_Z | FLAG_C ); \ + SETF( g_byTestTable[ byD1 ] | ( ( ( A ^ byD0 ) & ( A ^ byD1 ) & 0x80 ) ? FLAG_V : 0 ) | ( wD0 < 0x100 ) ); \ + A = byD1; + +#define DEC(a) wA0 = a; byD0 = K6502_Read( wA0 ); --byD0; K6502_Write( wA0, byD0 ); TEST( byD0 ) +#define INC(a) wA0 = a; byD0 = K6502_Read( wA0 ); ++byD0; K6502_Write( wA0, byD0 ); TEST( byD0 ) + +// Shift Op. +#define ASLA RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_ASLTable[ A ].byFlag ); A = g_ASLTable[ A ].byValue +#define ASL(a) RSTF( FLAG_N | FLAG_Z | FLAG_C ); wA0 = a; byD0 = K6502_Read( wA0 ); SETF( g_ASLTable[ byD0 ].byFlag ); K6502_Write( wA0, g_ASLTable[ byD0 ].byValue ) +#define LSRA RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_LSRTable[ A ].byFlag ); A = g_LSRTable[ A ].byValue +#define LSR(a) RSTF( FLAG_N | FLAG_Z | FLAG_C ); wA0 = a; byD0 = K6502_Read( wA0 ); SETF( g_LSRTable[ byD0 ].byFlag ); K6502_Write( wA0, g_LSRTable[ byD0 ].byValue ) +#define ROLA byD0 = F & FLAG_C; RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_ROLTable[ byD0 ][ A ].byFlag ); A = g_ROLTable[ byD0 ][ A ].byValue +#define ROL(a) byD1 = F & FLAG_C; RSTF( FLAG_N | FLAG_Z | FLAG_C ); wA0 = a; byD0 = K6502_Read( wA0 ); SETF( g_ROLTable[ byD1 ][ byD0 ].byFlag ); K6502_Write( wA0, g_ROLTable[ byD1 ][ byD0 ].byValue ) +#define RORA byD0 = F & FLAG_C; RSTF( FLAG_N | FLAG_Z | FLAG_C ); SETF( g_RORTable[ byD0 ][ A ].byFlag ); A = g_RORTable[ byD0 ][ A ].byValue +#define ROR(a) byD1 = F & FLAG_C; RSTF( FLAG_N | FLAG_Z | FLAG_C ); wA0 = a; byD0 = K6502_Read( wA0 ); SETF( g_RORTable[ byD1 ][ byD0 ].byFlag ); K6502_Write( wA0, g_RORTable[ byD1 ][ byD0 ].byValue ) + +// Jump Op. +#define JSR wA0 = AA_ABS2; PUSHW( PC ); PC = wA0; +#define BRA(a) if ( a ) { wA0 = PC; PC += (signed char)K6502_Read( PC ); CLK( 3 + ( ( wA0 & 0x0100 ) != ( PC & 0x0100 ) ) ); ++PC; } else { ++PC; CLK( 2 ); } +#define JMP(a) PC = a; + +/*-------------------------------------------------------------------*/ +/* Global valiables */ +/*-------------------------------------------------------------------*/ + +// 6502 Register +WORD PC; +BYTE SP; +BYTE F; +BYTE A; +BYTE X; +BYTE Y; + +// The state of the IRQ pin +BYTE IRQ_State; + +// Wiring of the IRQ pin +BYTE IRQ_Wiring; + +// The state of the NMI pin +BYTE NMI_State; + +// Wiring of the NMI pin +BYTE NMI_Wiring; + +// The number of the clocks that it passed +WORD g_wPassedClocks; + +// A table for the test +BYTE g_byTestTable[ 256 ]; + +// Value and Flag Data +struct value_table_tag +{ + BYTE byValue; + BYTE byFlag; +}; + +// A table for ASL +struct value_table_tag g_ASLTable[ 256 ]; + +// A table for LSR +struct value_table_tag g_LSRTable[ 256 ]; + +// A table for ROL +struct value_table_tag g_ROLTable[ 2 ][ 256 ]; + +// A table for ROR +struct value_table_tag g_RORTable[ 2 ][ 256 ]; + +/*===================================================================*/ +/* */ +/* K6502_Init() : Initialize K6502 */ +/* */ +/*===================================================================*/ +void K6502_Init() +{ +/* + * Initialize K6502 + * + * You must call this function only once at first. + */ + + BYTE idx; + BYTE idx2; + + // The establishment of the IRQ pin + NMI_Wiring = NMI_State = 1; + IRQ_Wiring = IRQ_State = 1; + + // Make a table for the test + idx = 0; + do + { + if ( idx == 0 ) + g_byTestTable[ 0 ] = FLAG_Z; + else + if ( idx > 127 ) + g_byTestTable[ idx ] = FLAG_N; + else + g_byTestTable[ idx ] = 0; + + ++idx; + } while ( idx != 0 ); + + // Make a table ASL + idx = 0; + do + { + g_ASLTable[ idx ].byValue = idx << 1; + g_ASLTable[ idx ].byFlag = 0; + + if ( idx > 127 ) + g_ASLTable[ idx ].byFlag = FLAG_C; + + if ( g_ASLTable[ idx ].byValue == 0 ) + g_ASLTable[ idx ].byFlag |= FLAG_Z; + else + if ( g_ASLTable[ idx ].byValue & 0x80 ) + g_ASLTable[ idx ].byFlag |= FLAG_N; + + ++idx; + } while ( idx != 0 ); + + // Make a table LSR + idx = 0; + do + { + g_LSRTable[ idx ].byValue = idx >> 1; + g_LSRTable[ idx ].byFlag = 0; + + if ( idx & 1 ) + g_LSRTable[ idx ].byFlag = FLAG_C; + + if ( g_LSRTable[ idx ].byValue == 0 ) + g_LSRTable[ idx ].byFlag |= FLAG_Z; + + ++idx; + } while ( idx != 0 ); + + // Make a table ROL + for ( idx2 = 0; idx2 < 2; ++idx2 ) + { + idx = 0; + do + { + g_ROLTable[ idx2 ][ idx ].byValue = ( idx << 1 ) | idx2; + g_ROLTable[ idx2 ][ idx ].byFlag = 0; + + if ( idx > 127 ) + g_ROLTable[ idx2 ][ idx ].byFlag = FLAG_C; + + if ( g_ROLTable[ idx2 ][ idx ].byValue == 0 ) + g_ROLTable[ idx2 ][ idx ].byFlag |= FLAG_Z; + else + if ( g_ROLTable[ idx2 ][ idx ].byValue & 0x80 ) + g_ROLTable[ idx2 ][ idx ].byFlag |= FLAG_N; + + ++idx; + } while ( idx != 0 ); + } + + // Make a table ROR + for ( idx2 = 0; idx2 < 2; ++idx2 ) + { + idx = 0; + do + { + g_RORTable[ idx2 ][ idx ].byValue = ( idx >> 1 ) | ( idx2 << 7 ); + g_RORTable[ idx2 ][ idx ].byFlag = 0; + + if ( idx & 1 ) + g_RORTable[ idx2 ][ idx ].byFlag = FLAG_C; + + if ( g_RORTable[ idx2 ][ idx ].byValue == 0 ) + g_RORTable[ idx2 ][ idx ].byFlag |= FLAG_Z; + else + if ( g_RORTable[ idx2 ][ idx ].byValue & 0x80 ) + g_RORTable[ idx2 ][ idx ].byFlag |= FLAG_N; + + ++idx; + } while ( idx != 0 ); + } +} + +/*===================================================================*/ +/* */ +/* K6502_Reset() : Reset a CPU */ +/* */ +/*===================================================================*/ +void K6502_Reset() +{ +/* + * Reset a CPU + * + */ + + // Reset Registers + PC = K6502_ReadW( VECTOR_RESET ); + SP = 0xFF; + A = X = Y = 0; + F = FLAG_Z | FLAG_R; + + // Set up the state of the Interrupt pin. + NMI_State = NMI_Wiring; + IRQ_State = IRQ_Wiring; + + // Reset Passed Clocks + g_wPassedClocks = 0; +} + +/*===================================================================*/ +/* */ +/* K6502_Set_Int_Wiring() : Set up wiring of the interrupt pin */ +/* */ +/*===================================================================*/ +void K6502_Set_Int_Wiring( BYTE byNMI_Wiring, BYTE byIRQ_Wiring ) +{ +/* + * Set up wiring of the interrupt pin + * + */ + + NMI_Wiring = byNMI_Wiring; + IRQ_Wiring = byIRQ_Wiring; +} + +int dbgstep = 0; +int check_userbutton(); + +/*===================================================================*/ +/* */ +/* K6502_Step() : */ +/* Only the specified number of the clocks execute Op. */ +/* */ +/*===================================================================*/ +void K6502_Step( WORD wClocks ) +{ +/* + * Only the specified number of the clocks execute Op. + * + * Parameters + * WORD wClocks (Read) + * The number of the clocks + */ + + BYTE byCode; + + WORD wA0; + BYTE byD0; + BYTE byD1; + WORD wD0; + + // Dispose of it if there is an interrupt requirement + if ( NMI_State != NMI_Wiring ) + { + // NMI Interrupt + CLK( 7 ); + + PUSHW( PC ); + PUSH( F & ~FLAG_B ); + + RSTF( FLAG_D ); + + PC = K6502_ReadW( VECTOR_NMI ); + } + else + if ( IRQ_State != IRQ_Wiring ) + { + // IRQ Interrupt + // Execute IRQ if an I flag isn't being set + if ( !( F & FLAG_I ) ) + { + CLK( 7 ); + + PUSHW( PC ); + PUSH( F & ~FLAG_B ); + + RSTF( FLAG_D ); + SETF( FLAG_I ); + + PC = K6502_ReadW( VECTOR_IRQ ); + } + } + + NMI_State = NMI_Wiring; + IRQ_State = IRQ_Wiring; + + // It has a loop until a constant clock passes + while ( g_wPassedClocks < wClocks ) + { + // Read an instruction + byCode = K6502_Read( PC++ ); + + //if (dbgstep % 10000 == 0) + //{ + // printf("%8d PC:%4x Code:%2x SP:%2x F:%2x A:%2x X:%2x Y:%2x\r\n", dbgstep, PC - 1, byCode, SP, F, A, X, Y); + // while (check_userbutton() != 0) ; + // wait(0.1); + //} + //dbgstep++; + + // Execute an instruction. + switch ( byCode ) + { + case 0x00: // BRK + ++PC; PUSHW( PC ); SETF( FLAG_B ); PUSH( F ); SETF( FLAG_I ); RSTF( FLAG_D ); PC = K6502_ReadW( VECTOR_IRQ ); CLK( 7 ); + break; + + case 0x01: // ORA (Zpg,X) + ORA( A_IX ); CLK( 6 ); + break; + + case 0x05: // ORA Zpg + ORA( A_ZP ); CLK( 3 ); + break; + + case 0x06: // ASL Zpg + ASL( AA_ZP ); CLK( 5 ); + break; + + case 0x08: // PHP + PUSH( F ); CLK( 3 ); + break; + + case 0x09: // ORA #Oper + ORA( A_IMM ); CLK( 2 ); + break; + + case 0x0A: // ASL A + ASLA; CLK( 2 ); + break; + + case 0x0D: // ORA Abs + ORA( A_ABS ); CLK( 4 ); + break; + + case 0x0e: // ASL Abs + ASL( AA_ABS ); CLK( 6 ); + break; + + case 0x10: // BPL Oper + BRA( !( F & FLAG_N ) ); + break; + + case 0x11: // ORA (Zpg),Y + ORA( A_IY ); CLK( 5 ); + break; + + case 0x15: // ORA Zpg,X + ORA( A_ZPX ); CLK( 4 ); + break; + + case 0x16: // ASL Zpg,X + ASL( AA_ZPX ); CLK( 6 ); + break; + + case 0x18: // CLC + RSTF( FLAG_C ); CLK( 2 ); + break; + + case 0x19: // ORA Abs,Y + ORA( A_ABSY ); CLK( 4 ); + break; + + case 0x1D: // ORA Abs,X + ORA( A_ABSX ); CLK( 4 ); + break; + + case 0x1E: // ASL Abs,X + ASL( AA_ABSX ); CLK( 7 ); + break; + + case 0x20: // JSR Abs + JSR; CLK( 6 ); + break; + + case 0x21: // AND (Zpg,X) + AND( A_IX ); CLK( 6 ); + break; + + case 0x24: // BIT Zpg + BIT( A_ZP ); CLK( 3 ); + break; + + case 0x25: // AND Zpg + AND( A_ZP ); CLK( 3 ); + break; + + case 0x26: // ROL Zpg + ROL( AA_ZP ); CLK( 5 ); + break; + + case 0x28: // PLP + POP( F ); SETF( FLAG_R ); CLK( 4 ); + break; + + case 0x29: // AND #Oper + AND( A_IMM ); CLK( 2 ); + break; + + case 0x2A: // ROL A + ROLA; CLK( 2 ); + break; + + case 0x2C: // BIT Abs + BIT( A_ABS ); CLK( 4 ); + break; + + case 0x2D: // AND Abs + AND( A_ABS ); CLK( 4 ); + break; + + case 0x2E: // ROL Abs + ROL( AA_ABS ); CLK( 6 ); + break; + + case 0x30: // BMI Oper + BRA( F & FLAG_N ); + break; + + case 0x31: // AND (Zpg),Y + AND( A_IY ); CLK( 5 ); + break; + + case 0x35: // AND Zpg,X + AND( A_ZPX ); CLK( 4 ); + break; + + case 0x36: // ROL Zpg,X + ROL( AA_ZPX ); CLK( 6 ); + break; + + case 0x38: // SEC + SETF( FLAG_C ); CLK( 2 ); + break; + + case 0x39: // AND Abs,Y + AND( A_ABSY ); CLK( 4 ); + break; + + case 0x3D: // AND Abs,X + AND( A_ABSX ); CLK( 4 ); + break; + + case 0x3E: // ROL Abs,X + ROL( AA_ABSX ); CLK( 7 ); + break; + + case 0x40: // RTI + POP( F ); SETF( FLAG_R ); POPW( PC ); CLK( 6 ); + break; + + case 0x41: // EOR (Zpg,X) + EOR( A_IX ); CLK( 6 ); + break; + + case 0x45: // EOR Zpg + EOR( A_ZP ); CLK( 3 ); + break; + + case 0x46: // LSR Zpg + LSR( AA_ZP ); CLK( 5 ); + break; + + case 0x48: // PHA + PUSH( A ); CLK( 3 ); + break; + + case 0x49: // EOR #Oper + EOR( A_IMM ); CLK( 2 ); + break; + + case 0x4A: // LSR A + LSRA; CLK( 2 ); + break; + + case 0x4C: // JMP Abs + JMP( AA_ABS ); CLK( 3 ); + break; + + case 0x4D: // EOR Abs + EOR( A_ABS ); CLK( 4 ); + break; + + case 0x4E: // LSR Abs + LSR( AA_ABS ); CLK( 6 ); + break; + + case 0x50: // BVC + BRA( !( F & FLAG_V ) ); + break; + + case 0x51: // EOR (Zpg),Y + EOR( A_IY ); CLK( 5 ); + break; + + case 0x55: // EOR Zpg,X + EOR( A_ZPX ); CLK( 4 ); + break; + + case 0x56: // LSR Zpg,X + LSR( AA_ZPX ); CLK( 6 ); + break; + + case 0x58: // CLI + byD0 = F; + RSTF( FLAG_I ); CLK( 2 ); + if ( ( byD0 & FLAG_I ) && IRQ_State == 0 ) + { + // IRQ Interrupt + // Execute IRQ if an I flag isn't being set + if ( !( F & FLAG_I ) ) + { + CLK( 7 ); + + PUSHW( PC ); + PUSH( F & ~FLAG_B ); + + RSTF( FLAG_D ); + SETF( FLAG_I ); + + PC = K6502_ReadW( VECTOR_IRQ ); + } + } + break; + + case 0x59: // EOR Abs,Y + EOR( A_ABSY ); CLK( 4 ); + break; + + case 0x5D: // EOR Abs,X + EOR( A_ABSX ); CLK( 4 ); + break; + + case 0x5E: // LSR Abs,X + LSR( AA_ABSX ); CLK( 7 ); + break; + + case 0x60: // RTS + POPW( PC ); ++PC; CLK( 6 ); + break; + + case 0x61: // ADC (Zpg,X) + ADC( A_IX ); CLK( 6 ); + break; + + case 0x65: // ADC Zpg + ADC( A_ZP ); CLK( 3 ); + break; + + case 0x66: // ROR Zpg + ROR( AA_ZP ); CLK( 5 ); + break; + + case 0x68: // PLA + POP( A ); TEST( A ); CLK( 4 ); + break; + + case 0x69: // ADC #Oper + ADC( A_IMM ); CLK( 2 ); + break; + + case 0x6A: // ROR A + RORA; CLK( 2 ); + break; + + case 0x6C: // JMP (Abs) + JMP( K6502_ReadW( AA_ABS ) ); CLK( 5 ); + break; + + case 0x6D: // ADC Abs + ADC( A_ABS ); CLK( 4 ); + break; + + case 0x6E: // ROR Abs + ROR( AA_ABS ); CLK( 6 ); + break; + + case 0x70: // BVS + BRA( F & FLAG_V ); + break; + + case 0x71: // ADC (Zpg),Y + ADC( A_IY ); CLK( 5 ); + break; + + case 0x75: // ADC Zpg,X + ADC( A_ZPX ); CLK( 4 ); + break; + + case 0x76: // ROR Zpg,X + ROR( AA_ZPX ); CLK( 6 ); + break; + + case 0x78: // SEI + SETF( FLAG_I ); CLK( 2 ); + break; + + case 0x79: // ADC Abs,Y + ADC( A_ABSY ); CLK( 4 ); + break; + + case 0x7D: // ADC Abs,X + ADC( A_ABSX ); CLK( 4 ); + break; + + case 0x7E: // ROR Abs,X + ROR( AA_ABSX ); CLK( 7 ); + break; + + case 0x81: // STA (Zpg,X) + STA( AA_IX ); CLK( 6 ); + break; + + case 0x84: // STY Zpg + STY( AA_ZP ); CLK( 3 ); + break; + + case 0x85: // STA Zpg + STA( AA_ZP ); CLK( 3 ); + break; + + case 0x86: // STX Zpg + STX( AA_ZP ); CLK( 3 ); + break; + + case 0x88: // DEY + --Y; TEST( Y ); CLK( 2 ); + break; + + case 0x8A: // TXA + A = X; TEST( A ); CLK( 2 ); + break; + + case 0x8C: // STY Abs + STY( AA_ABS ); CLK( 4 ); + break; + + case 0x8D: // STA Abs + STA( AA_ABS ); CLK( 4 ); + break; + + case 0x8E: // STX Abs + STX( AA_ABS ); CLK( 4 ); + break; + + case 0x90: // BCC + BRA( !( F & FLAG_C ) ); + break; + + case 0x91: // STA (Zpg),Y + STA( AA_IY ); CLK( 6 ); + break; + + case 0x94: // STY Zpg,X + STY( AA_ZPX ); CLK( 4 ); + break; + + case 0x95: // STA Zpg,X + STA( AA_ZPX ); CLK( 4 ); + break; + + case 0x96: // STX Zpg,Y + STX( AA_ZPY ); CLK( 4 ); + break; + + case 0x98: // TYA + A = Y; TEST( A ); CLK( 2 ); + break; + + case 0x99: // STA Abs,Y + STA( AA_ABSY ); CLK( 5 ); + break; + + case 0x9A: // TXS + SP = X; CLK( 2 ); + break; + + case 0x9D: // STA Abs,X + STA( AA_ABSX ); CLK( 5 ); + break; + + case 0xA0: // LDY #Oper + LDY( A_IMM ); CLK( 2 ); + break; + + case 0xA1: // LDA (Zpg,X) + LDA( A_IX ); CLK( 6 ); + break; + + case 0xA2: // LDX #Oper + LDX( A_IMM ); CLK( 2 ); + break; + + case 0xA4: // LDY Zpg + LDY( A_ZP ); CLK( 3 ); + break; + + case 0xA5: // LDA Zpg + LDA( A_ZP ); CLK( 3 ); + break; + + case 0xA6: // LDX Zpg + LDX( A_ZP ); CLK( 3 ); + break; + + case 0xA8: // TAY + Y = A; TEST( A ); CLK( 2 ); + break; + + case 0xA9: // LDA #Oper + LDA( A_IMM ); CLK( 2 ); + break; + + case 0xAA: // TAX + X = A; TEST( A ); CLK( 2 ); + break; + + case 0xAC: // LDY Abs + LDY( A_ABS ); CLK( 4 ); + break; + + case 0xAD: // LDA Abs + LDA( A_ABS ); CLK( 4 ); + break; + + case 0xAE: // LDX Abs + LDX( A_ABS ); CLK( 4 ); + break; + + case 0xB0: // BCS + BRA( F & FLAG_C ); + break; + + case 0xB1: // LDA (Zpg),Y + LDA( A_IY ); CLK( 5 ); + break; + + case 0xB4: // LDY Zpg,X + LDY( A_ZPX ); CLK( 4 ); + break; + + case 0xB5: // LDA Zpg,X + LDA( A_ZPX ); CLK( 4 ); + break; + + case 0xB6: // LDX Zpg,Y + LDX( A_ZPY ); CLK( 4 ); + break; + + case 0xB8: // CLV + RSTF( FLAG_V ); CLK( 2 ); + break; + + case 0xB9: // LDA Abs,Y + LDA( A_ABSY ); CLK( 4 ); + break; + + case 0xBA: // TSX + X = SP; TEST( X ); CLK( 2 ); + break; + + case 0xBC: // LDY Abs,X + LDY( A_ABSX ); CLK( 4 ); + break; + + case 0xBD: // LDA Abs,X + LDA( A_ABSX ); CLK( 4 ); + break; + + case 0xBE: // LDX Abs,Y + LDX( A_ABSY ); CLK( 4 ); + break; + + case 0xC0: // CPY #Oper + CPY( A_IMM ); CLK( 2 ); + break; + + case 0xC1: // CMP (Zpg,X) + CMP( A_IX ); CLK( 6 ); + break; + + case 0xC4: // CPY Zpg + CPY( A_ZP ); CLK( 3 ); + break; + + case 0xC5: // CMP Zpg + CMP( A_ZP ); CLK( 3 ); + break; + + case 0xC6: // DEC Zpg + DEC( AA_ZP ); CLK( 5 ); + break; + + case 0xC8: // INY + ++Y; TEST( Y ); CLK( 2 ); + break; + + case 0xC9: // CMP #Oper + CMP( A_IMM ); CLK( 2 ); + break; + + case 0xCA: // DEX + --X; TEST( X ); CLK( 2 ); + break; + + case 0xCC: // CPY Abs + CPY( A_ABS ); CLK( 4 ); + break; + + case 0xCD: // CMP Abs + CMP( A_ABS ); CLK( 4 ); + break; + + case 0xCE: // DEC Abs + DEC( AA_ABS ); CLK( 6 ); + break; + + case 0xD0: // BNE + BRA( !( F & FLAG_Z ) ); + break; + + case 0xD1: // CMP (Zpg),Y + CMP( A_IY ); CLK( 5 ); + break; + + case 0xD5: // CMP Zpg,X + CMP( A_ZPX ); CLK( 4 ); + break; + + case 0xD6: // DEC Zpg,X + DEC( AA_ZPX ); CLK( 6 ); + break; + + case 0xD8: // CLD + RSTF( FLAG_D ); CLK( 2 ); + break; + + case 0xD9: // CMP Abs,Y + CMP( A_ABSY ); CLK( 4 ); + break; + + case 0xDD: // CMP Abs,X + CMP( A_ABSX ); CLK( 4 ); + break; + + case 0xDE: // DEC Abs,X + DEC( AA_ABSX ); CLK( 7 ); + break; + + case 0xE0: // CPX #Oper + CPX( A_IMM ); CLK( 2 ); + break; + + case 0xE1: // SBC (Zpg,X) + SBC( A_IX ); CLK( 6 ); + break; + + case 0xE4: // CPX Zpg + CPX( A_ZP ); CLK( 3 ); + break; + + case 0xE5: // SBC Zpg + SBC( A_ZP ); CLK( 3 ); + break; + + case 0xE6: // INC Zpg + INC( AA_ZP ); CLK( 5 ); + break; + + case 0xE8: // INX + ++X; TEST( X ); CLK( 2 ); + break; + + case 0xE9: // SBC #Oper + SBC( A_IMM ); CLK( 2 ); + break; + + case 0xEA: // NOP + CLK( 2 ); + break; + + case 0xEC: // CPX Abs + CPX( A_ABS ); CLK( 4 ); + break; + + case 0xED: // SBC Abs + SBC( A_ABS ); CLK( 4 ); + break; + + case 0xEE: // INC Abs + INC( AA_ABS ); CLK( 6 ); + break; + + case 0xF0: // BEQ + BRA( F & FLAG_Z ); + break; + + case 0xF1: // SBC (Zpg),Y + SBC( A_IY ); CLK( 5 ); + break; + + case 0xF5: // SBC Zpg,X + SBC( A_ZPX ); CLK( 4 ); + break; + + case 0xF6: // INC Zpg,X + INC( AA_ZPX ); CLK( 6 ); + break; + + case 0xF8: // SED + SETF( FLAG_D ); CLK( 2 ); + break; + + case 0xF9: // SBC Abs,Y + SBC( A_ABSY ); CLK( 4 ); + break; + + case 0xFD: // SBC Abs,X + SBC( A_ABSX ); CLK( 4 ); + break; + + case 0xFE: // INC Abs,X + INC( AA_ABSX ); CLK( 7 ); + break; + + default: // Unknown Instruction + CLK( 2 ); + break; + + } /* end of switch ( byCode ) */ + + } /* end of while ... */ + + // Correct the number of the clocks + g_wPassedClocks -= wClocks; +} + +// Addressing Op. +// Data +// Absolute,X +static inline BYTE K6502_ReadAbsX(){ WORD wA0, wA1; wA0 = AA_ABS; wA1 = wA0 + X; CLK( ( wA0 & 0x0100 ) != ( wA1 & 0x0100 ) ); return K6502_Read( wA1 ); }; +// Absolute,Y +static inline BYTE K6502_ReadAbsY(){ WORD wA0, wA1; wA0 = AA_ABS; wA1 = wA0 + Y; CLK( ( wA0 & 0x0100 ) != ( wA1 & 0x0100 ) ); return K6502_Read( wA1 ); }; +// (Indirect),Y +static inline BYTE K6502_ReadIY(){ WORD wA0, wA1; wA0 = K6502_ReadZpW( K6502_Read( PC++ ) ); wA1 = wA0 + Y; CLK( ( wA0 & 0x0100 ) != ( wA1 & 0x0100 ) ); return K6502_Read( wA1 ); }; + +/*===================================================================*/ +/* */ +/* 6502 Reading/Writing Operation */ +/* */ +/*===================================================================*/ +#include "K6502_rw.h" + + +
diff -r 000000000000 -r 3dac1f1bc9e0 K6502.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/K6502.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,82 @@ +/*===================================================================*/ +/* */ +/* K6502.h : Header file for K6502 */ +/* */ +/* 1999/10/19 Racoon New preparation */ +/* */ +/*===================================================================*/ + +#ifndef K6502_H_INCLUDED +#define K6502_H_INCLUDED + +// Type definition +#ifndef DWORD +typedef unsigned long DWORD; +//typedef unsigned int DWORD; +#endif + +#ifndef WORD +typedef unsigned short WORD; +//typedef unsigned short WORD; +#endif + +#ifndef BYTE +typedef unsigned char BYTE; +//typedef char BYTE; +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* 6502 Flags */ +#define FLAG_C 0x01 +#define FLAG_Z 0x02 +#define FLAG_I 0x04 +#define FLAG_D 0x08 +#define FLAG_B 0x10 +#define FLAG_R 0x20 +#define FLAG_V 0x40 +#define FLAG_N 0x80 + +/* Stack Address */ +#define BASE_STACK 0x100 + +/* Interrupt Vectors */ +#define VECTOR_NMI 0xfffa +#define VECTOR_RESET 0xfffc +#define VECTOR_IRQ 0xfffe + +// NMI Request +#define NMI_REQ NMI_State = 0; + +// IRQ Request +#define IRQ_REQ IRQ_State = 0; + +// Emulator Operation +void K6502_Init(); +void K6502_Reset(); +void K6502_Set_Int_Wiring( BYTE byNMI_Wiring, BYTE byIRQ_Wiring ); +void K6502_Step( register WORD wClocks ); + +// I/O Operation (User definition) +static inline BYTE K6502_Read( WORD wAddr); +static inline WORD K6502_ReadW( WORD wAddr ); +static inline BYTE K6502_ReadZp( BYTE byAddr ); +static inline WORD K6502_ReadZpW( BYTE byAddr ); +static inline BYTE K6502_ReadAbsX(); +static inline BYTE K6502_ReadAbsY(); +static inline BYTE K6502_ReadIY(); + +static inline void K6502_Write( WORD wAddr, BYTE byData ); +static inline void K6502_WriteW( WORD wAddr, WORD wData ); + +// The state of the IRQ pin +extern BYTE IRQ_State; + +// The state of the NMI pin +extern BYTE NMI_State; + +#endif /* !K6502_H_INCLUDED */ + +
diff -r 000000000000 -r 3dac1f1bc9e0 K6502_rw.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/K6502_rw.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,363 @@ +/*===================================================================*/ +/* */ +/* K6502_RW.h : 6502 Reading/Writing Operation for NES */ +/* This file is included in K6502.cpp */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* */ +/*===================================================================*/ + +#ifndef K6502_RW_H_INCLUDED +#define K6502_RW_H_INCLUDED + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "pNesX.h" +#include "pNesX_System.h" + +/*===================================================================*/ +/* */ +/* K6502_ReadZp() : Reading from the zero page */ +/* */ +/*===================================================================*/ +static inline BYTE K6502_ReadZp( BYTE byAddr ) +{ +/* + * Reading from the zero page + * + * Parameters + * BYTE byAddr (Read) + * An address inside the zero page + * + * Return values + * Read Data + */ + + return RAM[ byAddr ]; +} + +/*===================================================================*/ +/* */ +/* K6502_Read() : Reading operation */ +/* */ +/*===================================================================*/ +static inline BYTE K6502_Read( WORD wAddr ) +{ +/* + * Reading operation + * + * Parameters + * WORD wAddr (Read) + * Address to read + * + * Return values + * Read data + * + * Remarks + * 0x0000 - 0x1fff RAM ( 0x800 - 0x1fff is mirror of 0x0 - 0x7ff ) + * 0x2000 - 0x3fff PPU + * 0x4000 - 0x5fff Sound + * 0x6000 - 0x7fff SRAM ( Battery Backed ) + * 0x8000 - 0xffff ROM + * + */ + BYTE byRet; + + switch ( wAddr & 0xe000 ) + { + case 0x0000: /* RAM */ + return RAM[ wAddr & 0x7ff ]; + + case 0x2000: /* PPU */ + if ( wAddr <= 0x2006 ) /* PPU Status */ + { + // Set return value + byRet = PPU_R2; + + // Reset a V-Blank flag + PPU_R2 &= ~R2_IN_VBLANK; + + // Reset address latch + PPU_Latch_Flag = 0; + + // Make a Nametable 0 in V-Blank + if ( PPU_Scanline >= SCAN_VBLANK_START && !( PPU_R0 & R0_NMI_VB ) ) + { + PPU_R0 &= ~R0_NAME_ADDR; + PPU_NameTableBank = NAME_TABLE0; + } + return byRet; + } + else + if ( wAddr == 0x2007 ) /* PPU Memory */ + { + // Set return value; + byRet = PPU_R7; + + // Read PPU Memory + PPU_R7 = PPUBANK[ PPU_Addr >> 10 ][ PPU_Addr & 0x3ff ]; + + // Increment PPU Address + PPU_Addr += PPU_Increment; + PPU_Addr &= 0x3fff; + + return byRet; + } + break; + + case 0x4000: /* Sound */ + if ( wAddr < 0x4016 ) + { + // Return APU Register + //return APU_Reg[ wAddr & 0x1f ]; + return ApuRead( wAddr & 0x1f ); + } + else + if ( wAddr == 0x4016 ) + { + // Set Joypad1 data + byRet = (BYTE)( ( PAD1_Latch >> PAD1_Bit ) & 1 ) | 0x40; + PAD1_Bit = ( PAD1_Bit == 23 ) ? 0 : ( PAD1_Bit + 1 ); + return byRet; + } + else + if ( wAddr == 0x4017 ) + { + // Set Joypad2 data + byRet = (BYTE)( ( PAD2_Latch >> PAD2_Bit ) & 1 ) | 0x40; + PAD2_Bit = ( PAD2_Bit == 23 ) ? 0 : ( PAD2_Bit + 1 ); + return byRet; + } + break; + + case 0x6000: /* SRAM */ + return SRAM[ wAddr & 0x1fff ]; + + case 0x8000: /* ROM BANK 0 */ + return ROMBANK0[ wAddr & 0x1fff ]; + + case 0xa000: /* ROM BANK 1 */ + return ROMBANK1[ wAddr & 0x1fff ]; + + case 0xc000: /* ROM BANK 2 */ + return ROMBANK2[ wAddr & 0x1fff ]; + + case 0xe000: /* ROM BANK 3 */ + return ROMBANK3[ wAddr & 0x1fff ]; + } + + return 0; +} + +/*===================================================================*/ +/* */ +/* K6502_Write() : Writing operation */ +/* */ +/*===================================================================*/ +static inline void K6502_Write( WORD wAddr, BYTE byData ) +{ +/* + * Writing operation + * + * Parameters + * WORD wAddr (Read) + * Address to write + * + * BYTE byData (Read) + * Data to write + * + * Remarks + * 0x0000 - 0x1fff RAM ( 0x800 - 0x1fff is mirror of 0x0 - 0x7ff ) + * 0x2000 - 0x3fff PPU + * 0x4000 - 0x5fff Sound + * 0x6000 - 0x7fff SRAM ( Battery Backed ) + * 0x8000 - 0xffff ROM + * + */ + + switch ( wAddr & 0xe000 ) + { + case 0x0000: /* RAM */ + RAM[ wAddr & 0x7ff ] = byData; + break; + + case 0x2000: /* PPU */ + switch ( wAddr & 0x7 ) + { + case 0: /* 0x2000 */ + PPU_R0 = byData; + PPU_Increment = ( PPU_R0 & R0_INC_ADDR ) ? 32 : 1; + PPU_NameTableBank = NAME_TABLE0 + ( PPU_R0 & R0_NAME_ADDR ); + PPU_BG_Base = ( PPU_R0 & R0_BG_ADDR ) ? ChrBuf + 256 * 64 : ChrBuf; + PPU_SP_Base = ( PPU_R0 & R0_SP_ADDR ) ? ChrBuf + 256 * 64 : ChrBuf; + PPU_SP_Height = ( PPU_R0 & R0_SP_SIZE ) ? 16 : 8; + break; + + case 1: /* 0x2001 */ + PPU_R1 = byData; + break; + + case 2: /* 0x2002 */ + PPU_R2 = byData; + break; + + case 3: /* 0x2003 */ + // Sprite RAM Address + PPU_R3 = byData; + break; + + case 4: /* 0x2004 */ + // Write data to Sprite RAM + SPRRAM[ PPU_R3++ ] = byData; + break; + + case 5: /* 0x2005 */ + // Set Scroll Register + if ( PPU_Latch_Flag ) + { + // V-Scroll Register + PPU_Scr_V_Next = ( byData > 239 ) ? 0 : byData; + PPU_Scr_V_Byte_Next = PPU_Scr_V_Next >> 3; + PPU_Scr_V_Bit_Next = PPU_Scr_V_Next & 7; + } + else + { + // H-Scroll Register + PPU_Scr_H_Next = byData; + PPU_Scr_H_Byte_Next = PPU_Scr_H_Next >> 3; + PPU_Scr_H_Bit_Next = PPU_Scr_H_Next & 7; + } + PPU_Latch_Flag ^= 1; + break; + + case 6: /* 0x2006 */ + // Set PPU Address + if ( PPU_Latch_Flag ) + { + // Low + PPU_Addr |= byData; + } + else + { + // High + PPU_Addr = ( byData & 0x3f ) << 8; + } + PPU_Latch_Flag ^= 1; + break; + + case 7: /* 0x2007 */ + // Write to PPU Memory + if ( PPU_Addr < 0x2000 && NesHeader.byVRomSize == 0 ) + { + // Pattern Data + ChrBufUpdate |= ( 1 << ( PPU_Addr >> 10 ) ); + PPURAM[ PPU_Addr ] = byData; + } + else + if ( PPU_Addr < 0x3f00 ) /* 0x2000 - 0x3eff */ + { + // Name Table + PPUBANK[ PPU_Addr >> 10 ][ PPU_Addr & 0x3ff ] = byData; + } + else + if ( !( PPU_Addr & 0xf ) ) /* 0x3f00 or 0x3f10 */ + { + // Palette mirror + PPURAM[ 0x3f10 ] = PPURAM[ 0x3f14 ] = PPURAM[ 0x3f18 ] = PPURAM[ 0x3f1c ] = + PPURAM[ 0x3f00 ] = PPURAM[ 0x3f04 ] = PPURAM[ 0x3f08 ] = PPURAM[ 0x3f0c ] = byData; + PalTable[ 0x00 ] = PalTable[ 0x04 ] = PalTable[ 0x08 ] = PalTable[ 0x0c ] = + PalTable[ 0x10 ] = PalTable[ 0x14 ] = PalTable[ 0x18 ] = PalTable[ 0x1c ] = NesPalette[ byData ]; // | 0x8000; + } + else + if ( PPU_Addr & 3 ) + { + // Palette + PPURAM[ PPU_Addr ] = byData; + PalTable[ PPU_Addr & 0x1f ] = NesPalette[ byData ]; + } + + // Increment PPU Address + PPU_Addr += PPU_Increment; + PPU_Addr &= 0x3fff; + break; + } + break; + + case 0x4000: /* Sound */ + switch ( wAddr & 0x1f ) + { + case 0x14: /* 0x4014 */ + // Sprite DMA + switch ( byData >> 5 ) + { + case 0x0: /* RAM */ + pNesX_MemoryCopy( SPRRAM, &RAM[ ( (WORD)byData << 8 ) & 0x7ff ], SPRRAM_SIZE ); + break; + + case 0x3: /* SRAM */ + pNesX_MemoryCopy( SPRRAM, &SRAM[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE ); + break; + + case 0x4: /* ROM BANK 0 */ + pNesX_MemoryCopy( SPRRAM, &ROMBANK0[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE ); + break; + + case 0x5: /* ROM BANK 1 */ + pNesX_MemoryCopy( SPRRAM, &ROMBANK1[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE ); + break; + + case 0x6: /* ROM BANK 2 */ + pNesX_MemoryCopy( SPRRAM, &ROMBANK2[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE ); + break; + + case 0x7: /* ROM BANK 3 */ + pNesX_MemoryCopy( SPRRAM, &ROMBANK3[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE ); + break; + } + APU_Reg[ 0x14 ] = byData; + break; + + case 0x16: /* 0x4016 */ + // Reset joypad + if ( !( APU_Reg[ 0x16 ] & 1 ) && ( byData & 1 ) ) + { + PAD1_Bit = 0; + PAD2_Bit = 0; + } + APU_Reg[ 0x16 ] = byData; + break; + + default: + if ( wAddr <= 0x4017 ) + { + // Write to APU Register + ApuWrite( wAddr & 0x1f, byData ); + } + break; + } + break; + + case 0x6000: /* SRAM */ + SRAM[ wAddr & 0x1fff ] = byData; + break; + + case 0x8000: /* ROM BANK 0 */ + case 0xa000: /* ROM BANK 1 */ + case 0xc000: /* ROM BANK 2 */ + case 0xe000: /* ROM BANK 3 */ + // Write to Mapper + MapperWrite( wAddr, byData ); + break; + } +} + +// Reading/Writing operation (WORD version) +static inline WORD K6502_ReadW( WORD wAddr ){ return K6502_Read( wAddr ) | (WORD)K6502_Read( wAddr + 1 ) << 8; }; +static inline void K6502_WriteW( WORD wAddr, WORD wData ){ K6502_Write( wAddr, wData & 0xff ); K6502_Write( wAddr + 1, wData >> 8 ); }; +static inline WORD K6502_ReadZpW( BYTE byAddr ){ return K6502_ReadZp( byAddr ) | ( K6502_ReadZp( byAddr + 1 ) << 8 ); }; + +#endif /* !K6502_RW_H_INCLUDED */ + +
diff -r 000000000000 -r 3dac1f1bc9e0 Racoon_logo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Racoon_logo.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,54 @@ +/*===================================================================*/ +/* */ +/* Racoon_logo.cpp : Racoon Logo image data(4bit bmp) */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +extern const unsigned char Racoon_logo[]; + +const unsigned char Racoon_logo[]= +{ + 0x42,0x4D,0x6E,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x00,0x00,0x28,0x00, + 0x00,0x00,0x3D,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0xF5,0xF5,0xF5,0x00,0xEF,0xEF, + 0xEF,0x00,0xE3,0xE3,0xE3,0x00,0xD2,0xD2,0xD2,0x00,0xC2,0xC2,0xC2,0x00,0xAC,0xAC, + 0xAC,0x00,0x9E,0x9E,0x9E,0x00,0x80,0x80,0x80,0x00,0x68,0x68,0x68,0x00,0x4D,0x4D, + 0x4D,0x00,0x2E,0x2E,0x2E,0x00,0x17,0x17,0x17,0x00,0x09,0x09,0x09,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x27,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x73,0x00,0x00,0x00,0x00,0x00, + 0x5C,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD, + 0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xDD,0xC6,0x10,0x00,0x00,0x00,0x00, + 0x26,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, + 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x63,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x04,0x97,0x22,0x69,0x84,0x8A,0x97,0x94,0x14,0x8A,0xA7,0x33,0x8A,0xA7, + 0x31,0x26,0x9A,0x94,0x24,0x97,0x13,0x96,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCA,0x35,0xBC,0x68,0xCA,0x9C,0xD6,0x4A,0xCA,0xAA,0x59,0xCA,0xAD, + 0x93,0x7C,0xB9,0xCB,0x46,0xDA,0x15,0xCA,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCA,0x4A,0xD9,0x28,0xC8,0x39,0xD6,0x7C,0xA3,0x34,0x6B,0xA4,0x4B, + 0xC6,0xAC,0x52,0x9D,0x76,0xDB,0x05,0xCA,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCC,0xBD,0xB5,0x04,0xAB,0xBC,0xD6,0x8D,0x91,0x01,0x6C,0xA3,0x3A, + 0xD6,0xBC,0x30,0x8D,0x86,0xDA,0x25,0xC9,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCB,0x9B,0xC9,0x22,0x56,0x6B,0xD6,0x6C,0xB4,0x46,0x6B,0xB4,0x5B, + 0xB5,0xAC,0x63,0xAD,0x76,0xDB,0x57,0xC9,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCA,0x45,0xBC,0x43,0xAB,0xBC,0xA4,0x39,0xCB,0xBA,0x48,0xCB,0xBC, + 0x82,0x6B,0xBB,0xC9,0x36,0xCC,0xBB,0xC7,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCB,0x78,0xDC,0x32,0x68,0x88,0x41,0x02,0x68,0x85,0x21,0x57,0x85, + 0x20,0x04,0x78,0x62,0x13,0x66,0x58,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0xCD,0xDD,0xB8,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x02,0x33,0x33,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +
diff -r 000000000000 -r 3dac1f1bc9e0 SDFileSystem.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/neilt6/code/SDFileSystem/#3fa5eaf48e81
diff -r 000000000000 -r 3dac1f1bc9e0 TFT/spidma.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFT/spidma.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,107 @@ +/*===================================================================*/ +/* */ +/* spidma.cpp : SPI DMA function */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#include "mbed.h" +#include "stm32f4xx_hal.h" + +SPI_HandleTypeDef SpiHandle; + +/*-------------------------------------------------------------------*/ +/* callback */ +/*-------------------------------------------------------------------*/ +extern "C" { + void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) + { + static DMA_HandleTypeDef hdma_tx; + + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_SPI1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_6; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + hdma_tx.Instance = DMA2_Stream3; + hdma_tx.Init.Channel = DMA_CHANNEL_3; + hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_tx.Init.Mode = DMA_NORMAL; + hdma_tx.Init.Priority = DMA_PRIORITY_HIGH; + hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; + + HAL_DMA_Init(&hdma_tx); + + __HAL_LINKDMA(hspi, hdmatx, hdma_tx); + + HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 1); + HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); + } + + void DMA2_Stream3_IRQHandler(void) + { + HAL_DMA_IRQHandler(SpiHandle.hdmatx); + } + +} // extern "C" + +/*-------------------------------------------------------------------*/ +/* Write a byte data */ +/*-------------------------------------------------------------------*/ +void spi_write(uint8_t data) +{ + HAL_SPI_Transmit(&SpiHandle, &data, 1, 100); +} + +/*-------------------------------------------------------------------*/ +/* Write a word data */ +/*-------------------------------------------------------------------*/ +void spi_writew(uint16_t data) +{ + HAL_SPI_Transmit(&SpiHandle, (uint8_t *)&data, 2, 100); +} + +/*-------------------------------------------------------------------*/ +/* Initialize SPI DMA */ +/*-------------------------------------------------------------------*/ +void spi_init() +{ + SpiHandle.Instance = SPI1; + SpiHandle.Init.Mode = SPI_MODE_MASTER; + SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; + SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; + SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; + SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + SpiHandle.Init.CRCPolynomial = 7; + SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; + SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; + SpiHandle.Init.NSS = SPI_NSS_SOFT; + SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE; + + if (HAL_SPI_Init(&SpiHandle) != HAL_OK) + while(1); +} +
diff -r 000000000000 -r 3dac1f1bc9e0 TFT/spidma.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFT/spidma.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,19 @@ +/*===================================================================*/ +/* */ +/* spidma.h : SPI DMA function header */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#ifndef SPIDMA_H_INCLUDED +#define SPIDMA_H_INCLUDED + +void spi_init(); +void spi_write(uint8_t data); +void spi_writew(uint16_t data); + +extern SPI_HandleTypeDef SpiHandle; + +#endif +
diff -r 000000000000 -r 3dac1f1bc9e0 TFT/tft.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFT/tft.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,273 @@ +/*===================================================================*/ +/* */ +/* tft.cpp : TFT(ILI9341) function */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#include "mbed.h" +#include "tft.h" + +DigitalOut cs(PB_5, PullUp); // TFT chipselect pin +DigitalOut dc(PA_8, PullUp); // TFT data command select pin +DigitalOut rst(PA_10,PullUp); // TFT reset pin + +/*-------------------------------------------------------------------*/ +/* Write command */ +/*-------------------------------------------------------------------*/ +void write_cmd(uint8_t cmd) +{ + dc = 0; + spi_write(cmd); +} + +/*-------------------------------------------------------------------*/ +/* Write data */ +/*-------------------------------------------------------------------*/ +void write_data(uint8_t data) +{ + dc = 1; + spi_write(data); +} + +/*-------------------------------------------------------------------*/ +/* TFT reset */ +/*-------------------------------------------------------------------*/ +void tft_reset() +{ + wait_ms(200); + cs = 1; + dc = 1; + rst = 1; + wait_ms(200); + rst = 0; + wait_us(10); + rst = 1; + wait_ms(120); + cs = 0; + wait_ms(10); + + write_cmd(0x3A); // Pixel Format + write_data(0x55); // 16bit Color + + write_cmd(0xB1); // Frame Control + write_data(0); + write_data(0x1f); + + write_cmd(0x36); // Memory Access Control + write_data(0xE8); // MY MX MV BGR + + write_cmd(0x11); // Sleep Out + wait_ms(5); + + write_cmd(0x29); // Display On +} + +/*-------------------------------------------------------------------*/ +/* Set windows size, start memory write */ +/*-------------------------------------------------------------------*/ +void tft_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) +{ + write_cmd(0x2A); // Column Address Set + write_data(x0 >> 8); + write_data(x0); + write_data(x1 >> 8); + write_data(x1); + + write_cmd(0x2B); // Page Address Set + write_data(y0 >> 8); + write_data(y0); + write_data(y1 >> 8); + write_data(y1); + + write_cmd(0x2C); // Memory Write + + wait_us(20); + + dc = 1; +} + +/*-------------------------------------------------------------------*/ +/* Clear screen */ +/*-------------------------------------------------------------------*/ +void tft_clear(uint16_t color) +{ + tft_set_window(0, 0, TFT_WIDTH, TFT_HEIGHT); + + for (int i = 0; i < TFT_WIDTH * TFT_HEIGHT; ++i) + { + spi_writew(color); + } +} + +/*-------------------------------------------------------------------*/ +/* Put char */ +/*-------------------------------------------------------------------*/ +void tft_put_char(int x, int y, char chr, uint16_t color, uint16_t bgcolor) +{ + if (chr < 0x20 || chr > 0x7f) + { + chr = 0x3f; + } + else + { + chr = (chr < 0x60) ? chr - 0x20 : chr - 0x40; + } + + tft_set_window(x, y, x + 7, y + 6); + + for (int dy = 0; dy < 7; ++dy) + { + unsigned char img = chrimg[chr][dy]; + for ( int dx = 0; dx < 8; ++dx) + { + if (img & 0x80) + { + spi_writew(color); + } + else + { + spi_writew(bgcolor); + } + img <<= 1; + } + } + +} + +/*-------------------------------------------------------------------*/ +/* Text out */ +/*-------------------------------------------------------------------*/ +void tft_text(int x, int y, char *text, uint16_t color, uint16_t bgcolor) +{ + while (*text != 0) + { + tft_put_char(x, y, *text, color, bgcolor); + x += 8; + text++; + } +} + +/*-------------------------------------------------------------------*/ +/* Horizontal Line */ +/*-------------------------------------------------------------------*/ +void tft_hline(int x1, int y, int x2, uint16_t color) +{ + tft_set_window(x1, y, x2, y); + + for (;x1 < x2; ++x1) + { + spi_writew(color); + } +} + +/*-------------------------------------------------------------------*/ +/* Vertical Line */ +/*-------------------------------------------------------------------*/ +void tft_vline(int x, int y1, int y2, uint16_t color) +{ + tft_set_window(x, y1, x, y2); + + for (;y1 < y2; ++y1) + { + spi_writew(color); + } +} + +/*-------------------------------------------------------------------*/ +/* Box */ +/*-------------------------------------------------------------------*/ +void tft_box(int x1, int y1, int x2, int y2, uint16_t color) +{ + tft_hline(x1, y1, x2, color); + tft_vline(x1, y1, y2, color); + tft_vline(x2, y1, y2, color); + tft_hline(x1, y2, x2, color); +} + +/*-------------------------------------------------------------------*/ +/* Box Fill */ +/*-------------------------------------------------------------------*/ +void tft_boxfill(int x1, int y1, int x2, int y2, uint16_t color) +{ + tft_set_window(x1, y1, x2, y2); + + for (int i = 0; i < (x2 - x1 + 1) * (y2 - y1 + 1); ++i) + { + spi_writew(color); + } +} + +/*-------------------------------------------------------------------*/ +/* Draw 4bit BMP */ +/*-------------------------------------------------------------------*/ +bool draw_bmp_4bpp(const unsigned char *imgdata, int x, int y) +{ + BITMAPFILEHEADER *bf = (BITMAPFILEHEADER *)imgdata; + BITMAPINFOHEADER *bi = (BITMAPINFOHEADER *)(imgdata + sizeof(BITMAPFILEHEADER)); + + if (bi->biBitCount != 4) + { + return false; + } + + unsigned char *pRGBPal = (unsigned char*)imgdata + sizeof(BITMAPFILEHEADER) + bi->biSize; + unsigned short palette[16]; + + for (int i = 0; pRGBPal < imgdata + bf->bfOffBits && i < 16; ++i) + { + unsigned short r,g,b; + b = *pRGBPal++ >> 3; + g = *pRGBPal++ >> 2; + r = *pRGBPal++ >> 3; + pRGBPal++; + palette[i] = ((g & 7) << 13) | (b << 8) | (r << 3) | (g >> 3); + } + + unsigned short HLine[320]; + int linesize = (bi->biWidth / 2 + 3) & 0xfffc; + + tft_set_window(x, y, x + bi->biWidth - 1, y + bi->biHeight - 1); + + unsigned char *bmp; + + for (int y = bi->biHeight - 1; y >= 0; --y) + { + bmp = (unsigned char *)imgdata + bf->bfOffBits + y * linesize; + + for (int x = 0; x < bi->biWidth; ++x) + { + char pal; + if (x & 1) + { + pal = *bmp & 0xf; + bmp++; + } + else + { + pal = *bmp >> 4; + } + + HLine[x] = palette[pal]; + } + + HAL_SPI_Transmit(&SpiHandle, (uint8_t *)HLine, bi->biWidth * 2, 100); + } + + return true; +} + +/*-------------------------------------------------------------------*/ +/* Initialize TFT */ +/*-------------------------------------------------------------------*/ +void tft_init(void) +{ + spi_init(); + + tft_reset(); +} + + + +
diff -r 000000000000 -r 3dac1f1bc9e0 TFT/tft.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFT/tft.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,273 @@ +/*===================================================================*/ +/* */ +/* tft.h : TFT(ILI9341) function header */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#ifndef TFT_H +#define TFT_H + +#include "stm32f4xx_hal.h" +#include "spidma.h" + +#define TFT_WIDTH 320 +#define TFT_HEIGHT 240 + +#define TFT_WHITE 0xFFFF +#define TFT_WHITESMOKE 0xBFFF +#define TFT_GHOSTWHITE 0xDFFF +#define TFT_ALICEBLUE 0xDFF7 +#define TFT_LAVENDAR 0x5FEF +#define TFT_AZURE 0xFFF7 +#define TFT_LIGHTCYAN 0xFFE7 +#define TFT_MINTCREAM 0xFFFF +#define TFT_HONEYDEW 0xFEF7 +#define TFT_IVORY 0xFEFF +#define TFT_BEIGE 0xBCFF +#define TFT_LIGHTYELLOW 0xFCFF +#define TFT_LIGHTGOLDENRODYELLOW 0xFAFF +#define TFT_LEMONCHIFFON 0xFAFF +#define TFT_FLORALWHITE 0xFEFF +#define TFT_OLDLACE 0xBDFF +#define TFT_CORNSILK 0xDCFF +#define TFT_PAPAYAWHITE 0x9BFF +#define TFT_BLANCHEDALMOND 0x7AFF +#define TFT_BISQUE 0x39FF +#define TFT_SNOW 0xFFFF +#define TFT_LINEN 0x9DFF +#define TFT_ANTIQUEWHITE 0x7BFF +#define TFT_SEASHELL 0xBEFF +#define TFT_LAVENDERBLUSH 0x9FFF +#define TFT_MISTYROSE 0x3CFF +#define TFT_GAINSBORO 0xFCE6 +#define TFT_LIGHTGRAY 0xBAD6 +#define TFT_LIGHTSTEELBLUE 0x3CB6 +#define TFT_LIGHTBLUE 0xDDB6 +#define TFT_LIGHTSKYBLUE 0x9F8E +#define TFT_POWDERBLUE 0x1DB7 +#define TFT_PALETURQUOISE 0x9EB7 +#define TFT_SKYBLUE 0x9D8E +#define TFT_MEDIUMAQUAMARINE 0x756E +#define TFT_AQUAMARINE 0xFB87 +#define TFT_PALEGREEN 0xF39F +#define TFT_LIGHTGREEN 0x9297 +#define TFT_KHAKI 0x52F7 +#define TFT_PALEGOLDENROD 0x55F7 +#define TFT_MOCCASIN 0x37FF +#define TFT_NAVAJOWHITE 0x16FF +#define TFT_PEACHPUFF 0xF7FE +#define TFT_WHEAT 0x16FF +#define TFT_PINK 0x19FE +#define TFT_LIGHTPINK 0xD8FD +#define TFT_THISTLE 0x1BDE +#define TFT_PLUM 0x1CE5 +#define TFT_SILVER 0x18C6 +#define TFT_DARKGRAY 0x55AD +#define TFT_LIGHTSLATEGRAY 0x537C +#define TFT_SLATEGRAY 0x1274 +#define TFT_SLATEBLUE 0xFA6A +#define TFT_STEELBLUE 0x374C +#define TFT_MEDIUMSLATEBLUE 0x5E7B +#define TFT_ROYALBLUE 0x5C43 +#define TFT_BLUE 0x1F00 +#define TFT_DODGERBLUE 0x9F24 +#define TFT_CORNFLOWERBLUE 0xBE6C +#define TFT_DEEPSKYBLUE 0x1F06 +#define TFT_CYAN 0xFF07 +#define TFT_AQUA 0xFF07 +#define TFT_TURQUOISE 0x1A47 +#define TFT_MEDIUMTURQUOISE 0x9A4E +#define TFT_DARKTURQUOISE 0x9A06 +#define TFT_LIGHTSEAGREEN 0xB525 +#define TFT_MEDIUMSPRINGGREEN 0xF307 +#define TFT_SPRINGGREEN 0xF007 +#define TFT_LIME 0xE007 +#define TFT_LIMEGREEN 0x6636 +#define TFT_YELLOWGREEN 0x669E +#define TFT_LAWNGREEN 0xE087 +#define TFT_CHARTREUSE 0xE087 +#define TFT_GREENYELLOW 0xE6B7 +#define TFT_YELLOW 0xE0FF +#define TFT_GOLD 0xC0FE +#define TFT_ORANGE 0x20FD +#define TFT_DARKORANGE 0x60FC +#define TFT_GOLDENROD 0x24DD +#define TFT_BURLYWOOD 0xD1E5 +#define TFT_TAN 0xB2D5 +#define TFT_SANDYBROWN 0x2CFD +#define TFT_DARKSALMON 0xCFEC +#define TFT_LIGHTCORAL 0x10F4 +#define TFT_SALMON 0xEFC +#define TFT_LIGHTSALMON 0xFFD +#define TFT_CORAL 0xAFC +#define TFT_TOMATO 0x29FB +#define TFT_ORANGERED 0x20FA +#define TFT_RED 0xF8 +#define TFT_DEEPPINK 0xB2F8 +#define TFT_HOTPINK 0x57FB +#define TFT_PALEVIOLETRED 0x92DB +#define TFT_VIOLET 0x3EF4 +#define TFT_ORCHID 0x9BDB +#define TFT_MAGENTA 0x1FF8 +#define TFT_FUCHSIA 0x1FF8 +#define TFT_MEDIUMORCHID 0xBABA +#define TFT_DARKORCHID 0xBA99 +#define TFT_DARKVIOLET 0x1A98 +#define TFT_BLUEVIOLET 0x7C89 +#define TFT_MEDIUMPURPLE 0x9B93 +#define TFT_GRAY 0x1084 +#define TFT_MEDIUMBLUE 0x1A00 +#define TFT_DARKCYAN 0x7104 +#define TFT_CADETBLUE 0x1465 +#define TFT_DARKSEAGREEN 0xF295 +#define TFT_MEDIUMSEAGREEN 0xAE45 +#define TFT_TEAL 0x1004 +#define TFT_FORESTGREEN 0x6424 +#define TFT_SEAGREEN 0x6B34 +#define TFT_DARKKHAKI 0xCDC5 +#define TFT_PERU 0x28D4 +#define TFT_CRIMSON 0xA8E0 +#define TFT_INDIANRED 0xECD2 +#define TFT_ROSYBROWN 0x92C4 +#define TFT_MEDIUMVIOLETRED 0xB1C8 +#define TFT_DIMGRAY 0x4D6B +#define TFT_BLACK 0x0 +#define TFT_MIDNIGHTBLUE 0xCE18 +#define TFT_DARKSLATEBLUE 0xF149 +#define TFT_DARKBLUE 0x1100 +#define TFT_NAVY 0x1000 +#define TFT_DARKSLATEGRAY 0x8A32 +#define TFT_GREEN 0x4 +#define TFT_DARKGREEN 0x2003 +#define TFT_DARKOLIVEGREEN 0x665B +#define TFT_OLIVEDRAB 0x846C +#define TFT_OLIVE 0x84 +#define TFT_DARKGOLDENROD 0x41BC +#define TFT_CHOCOLATE 0x44D3 +#define TFT_SIENNA 0xA6A2 +#define TFT_SADDLEBROWN 0x228A +#define TFT_FIREBRICK 0x24B1 +#define TFT_BROWN 0x65A9 +#define TFT_MAROON 0x80 +#define TFT_DARKRED 0x88 +#define TFT_DARKMAGENTA 0x1188 +#define TFT_PURPLE 0x1080 +#define TFT_INDIGO 0x1048 + +const unsigned char chrimg[][7] = +{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20h SP + 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, // 21h ! + 0x00, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, // 22h " + 0x00, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x00, // 23h # + 0x10, 0x3c, 0x50, 0x38, 0x14, 0x78, 0x10, // 24h $ + 0x00, 0x32, 0x54, 0x68, 0x16, 0x2a, 0x4c, // 25h % + 0x18, 0x24, 0x14, 0x38, 0x4e, 0x44, 0x3a, // 26h & + 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, // 27h ' + 0x04, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, // 28h ( + 0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, // 29h ) + 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, // 2Ah * + 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, // 2Bh + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, // 2Ch , + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, // 2Dh - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, // 2Eh . + 0x00, 0x08, 0x08, 0x10, 0x20, 0x20, 0x00, // 2Fh / + + 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38, // 30h 0 + 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, // 31h 1 + 0x38, 0x44, 0x04, 0x18, 0x20, 0x40, 0x7c, // 32h 2 + 0x38, 0x44, 0x04, 0x18, 0x04, 0x44, 0x38, // 33h 3 + 0x08, 0x18, 0x28, 0x48, 0x7c, 0x08, 0x08, // 34h 4 + 0x7c, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, // 35h 5 + 0x38, 0x44, 0x40, 0x78, 0x44, 0x44, 0x38, // 36h 6 + 0x7c, 0x44, 0x04, 0x08, 0x08, 0x10, 0x10, // 37h 7 + 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, // 38h 8 + 0x38, 0x44, 0x44, 0x3c, 0x04, 0x44, 0x38, // 39h 9 + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, // 3Ah : + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x20, // 3Bh ; + 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, // 3Ch < + 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, // 3Dh = + 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, // 3Eh > + 0x38, 0x44, 0x44, 0x08, 0x10, 0x00, 0x10, // 3Fh > + + 0x7c, 0x82, 0xba, 0xa6, 0xbc, 0x80, 0x7c, // 40h @ + 0x38, 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, // 41h A + 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, // 42h B + 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, // 43h C + 0x70, 0x48, 0x44, 0x44, 0x44, 0x48, 0x70, // 44h D + 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7c, // 45h E + 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, // 46h F + 0x38, 0x44, 0x40, 0x4c, 0x44, 0x44, 0x38, // 47h G + 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, // 48h H + 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, // 49h I + 0x3c, 0x08, 0x08, 0x08, 0x08, 0x48, 0x30, // 4Ah J + 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, // 4Bh K + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, // 4CH L + 0x44, 0x6c, 0x54, 0x54, 0x44, 0x44, 0x44, // 4DH M + 0x44, 0x64, 0x54, 0x54, 0x4c, 0x44, 0x44, // 4EH N + 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, // 4FH O + + 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, // 50h P + 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, // 51h Q + 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x44, // 52h R + 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, // 53h S + 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 54h T + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, // 55h U + 0x44, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, // 56h V + 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x28, // 57h W + 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, // 58h X + 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, // 59h Y + 0x7c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7c, // 5Ah Z + 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, // 5Bh [ + 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, // 5Ch back slash + 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, // 5Dh ] + 0x00, 0x10, 0x28, 0x00, 0x00, 0x00, 0x00, // 5Eh ^ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c // 5Fh _ +}; + +#pragma pack(2) +typedef struct tagBITMAPFILEHEADER { + unsigned short bfType; + unsigned long bfSize; + unsigned short bfReserved1; + unsigned short bfReserved2; + unsigned long bfOffBits; +} BITMAPFILEHEADER; + +typedef struct tagBITMAPINFOHEADER{ + unsigned long biSize; + long biWidth; + long biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + unsigned long biCompression; + unsigned long biSizeImage; + long biXPixPerMeter; + long biYPixPerMeter; + unsigned long biClrUsed; + unsigned long biClrImporant; +} BITMAPINFOHEADER; +#pragma pack() + +#pragma pack(1) +typedef struct tagBMP24{ + unsigned char B; + unsigned char G; + unsigned char R; +} BMP24; +#pragma pack() + +void tft_init(); +void tft_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); +void tft_clear(uint16_t color); +void tft_put_char(int x, int y, char chr, uint16_t color, uint16_t bgcolor); +void tft_text(int x, int y, char *text, uint16_t color, uint16_t bgcolor); +void tft_hline(int x1, int y, int x2, uint16_t color); +void tft_vline(int x, int y1, int y2, uint16_t color); +void tft_box(int x1, int y1, int x2, int y2, uint16_t color); +void tft_boxfill(int x1, int y1, int x2, int y2, uint16_t color); +bool draw_bmp_4bpp(const unsigned char *imgdata, int x, int y); + +#endif +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/IUSBEnumerator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/IUSBEnumerator.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,37 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IUSBENUMERATOR_H_ +#define IUSBENUMERATOR_H_ + +#include "stdint.h" +#include "USBEndpoint.h" + +/* +Generic interface to implement for "smart" USB enumeration +*/ + +class IUSBEnumerator +{ +public: + virtual void setVidPid(uint16_t vid, uint16_t pid) = 0; + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used +}; + +#endif /*IUSBENUMERATOR_H_*/ + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBDeviceConnected.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBDeviceConnected.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,90 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "USBDeviceConnected.h" +#include "dbg.h" + +USBDeviceConnected::USBDeviceConnected() { + init(); +} + +void USBDeviceConnected::init() { + port = 0; + vid = 0; + pid = 0; + nb_interf = 0; + enumerated = false; + device_class = 0; + device_subclass = 0; + proto = 0; + lowSpeed = false; + hub_parent = NULL; +} + +bool USBDeviceConnected::addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) { + USB_DBG("intf_nb=%d", intf_nb); + if (intf.count(intf_nb) > 0) { + return false; + } + intf[intf_nb] = new INTERFACE(intf_class, intf_subclass, intf_protocol); + return true; +} + +bool USBDeviceConnected::addEndpoint(uint8_t intf_nb, USBEndpoint * ept) { + if (intf.count(intf_nb) > 0) { + intf[intf_nb]->ep.push_back(ept); + return true; + } + return false; +} + +void USBDeviceConnected::init(USBDeviceConnected* parent, uint8_t port_, bool lowSpeed_) { + USB_DBG("init dev: %p", this); + init(); + hub_parent = parent; + port = port_; + lowSpeed = lowSpeed_; +} + +void USBDeviceConnected::disconnect() { + //for(int i = 0; i < MAX_INTF; i++) { + // intf[i].detach.call(); + //} + //init(); +} + + +USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index) { + USB_DBG("intf_nb=%d", intf_nb); + USB_TEST_ASSERT(intf.count(intf_nb) > 0); + INTERFACE* inter = intf[intf_nb]; + for (int i = 0; i < inter->ep.size(); i++) { + if ((inter->ep[i]->getType() == type) && (inter->ep[i]->getDir() == dir)) { + if(index) { + index--; + } else { + return inter->ep[i]; + } + } + } + return NULL; +} + +USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, uint8_t index) { + USB_TEST_ASSERT(intf.count(intf_nb) > 0); + return intf[intf_nb]->ep[index]; +} +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBDeviceConnected.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBDeviceConnected.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,134 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "USBEndpoint.h" +#include "USBHostConf.h" +#include "myvector.h" +#include "mymap.h" + +class USBEndpoint; + +struct INTERFACE { + INTERFACE(uint8_t _class, uint8_t _subclass, uint8_t _protocol) { + intf_class = _class; + intf_subclass = _subclass; + intf_protocol = _protocol; + } + uint8_t intf_class; + uint8_t intf_subclass; + uint8_t intf_protocol; + myvector<USBEndpoint*>ep; +}; + +/** +* USBDeviceConnected class +*/ +class USBDeviceConnected { +public: + + /** + * Constructor + */ + USBDeviceConnected(); + + /** + * Attach an USBEndpoint to this device + * + * @param intf_nb interface number + * @param ep pointeur on the USBEndpoint which will be attached + * @returns true if successful, false otherwise + */ + bool addEndpoint(uint8_t intf_nb, USBEndpoint * ep); + + /** + * Retrieve an USBEndpoint by its TYPE and DIRECTION + * + * @param intf_nb the interface on which to lookup the USBEndpoint + * @param type type of the USBEndpoint looked for + * @param dir direction of the USBEndpoint looked for + * @param index the index of the USBEndpoint whitin the interface + * @returns pointer on the USBEndpoint if found, NULL otherwise + */ + USBEndpoint * getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index = 0); + + /** + * Retrieve an USBEndpoint by its index + * + * @param intf_nb interface number + * @param index index of the USBEndpoint + * @returns pointer on the USBEndpoint if found, NULL otherwise + */ + USBEndpoint * getEndpoint(uint8_t intf_nb, uint8_t index); + + /** + * Add a new interface to this device + * + * @param intf_nb interface number + * @param intf_class interface class + * @param intf_subclass interface subclass + * @param intf_protocol interface protocol + * @returns true if successful, false otherwise + */ + bool addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); + + /** + * Disconnect the device by calling a callback function registered by a driver + */ + void disconnect(); + + void init(USBDeviceConnected* parent, uint8_t _port, bool _lowSpeed); + void setAddress(uint8_t addr_) { addr = addr_; }; + void setVid(uint16_t vid_) { vid = vid_; }; + void setPid(uint16_t pid_) { pid = pid_; }; + void setClass(uint8_t device_class_) { device_class = device_class_; } + void setSubClass(uint8_t device_subclass_) { device_subclass = device_subclass_; }; + void setProtocol(uint8_t pr) { proto = pr; }; + void setEnumerated() { enumerated = true; }; + void setNbIntf(uint8_t nb_intf) {nb_interf = nb_intf; }; + void setSpeed(bool _lowSpeed) { lowSpeed = _lowSpeed; } + void setName(const char * name_, uint8_t intf_nb) { return; }; + void setEpCtl(USBEndpoint* ep) { ep_ctl = ep; } + + static int getNewAddress() { + static int addr = 1; + return addr++; + } + uint8_t getAddress() { return addr; }; + uint16_t getVid() { return vid; }; + uint16_t getPid() { return pid; }; + uint8_t getClass() { return device_class; }; + bool getSpeed() { return lowSpeed; } + bool isEnumerated() { return enumerated; }; + USBEndpoint* getEpCtl() { return ep_ctl; } + +private: + USBDeviceConnected* hub_parent; + mymap<int,INTERFACE*>intf; + uint8_t port; + uint16_t vid; + uint16_t pid; + uint8_t addr; + uint8_t device_class; + uint8_t device_subclass; + uint8_t proto; + bool lowSpeed; + bool enumerated; + uint8_t nb_interf; + USBEndpoint* ep_ctl; + void init(); +}; +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBEndpoint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBEndpoint.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,168 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include "FunctionPointer.h" +#include "USBHostTypes.h" +#include "USBDeviceConnected.h" + +class USBDeviceConnected; + +/** +* USBEndpoint class +*/ +class USBEndpoint { +public: + /** + * Constructor + */ + USBEndpoint(USBDeviceConnected* _dev) { + init(CONTROL_ENDPOINT, IN, 8, 0); + dev = _dev; + pData = NULL; + } + + /** + * Initialize an endpoint + * + * @param type endpoint type + * @param dir endpoint direction + * @param size endpoint size + * @param ep_number endpoint number + */ + void init(ENDPOINT_TYPE _type, ENDPOINT_DIRECTION _dir, uint32_t size, uint8_t ep_number) { + setState(USB_TYPE_FREE); + setType(_type); + dir = _dir; + MaxPacketSize = size; + address = ep_number; + data01_toggle = DATA0; + } + + void ohci_init(uint8_t frameCount, uint8_t queueLimit) { + ohci.frameCount = frameCount; + ohci.queueLimit = queueLimit; + } + + /** + * Attach a member function to call when a transfer is finished + * + * @param tptr pointer to the object to call the member function on + * @param mptr pointer to the member function to be called + */ + template<typename T> + inline void attach(T* tptr, void (T::*mptr)(void)) { + if((mptr != NULL) && (tptr != NULL)) { + rx.attach(tptr, mptr); + } + } + + /** + * Attach a callback called when a transfer is finished + * + * @param fptr function pointer + */ + inline void attach(void (*fptr)(void)) { + if(fptr != NULL) { + rx.attach(fptr); + } + } + + /** + * Call the handler associted to the end of a transfer + */ + inline void call() { + rx.call(); + }; + + void setType(ENDPOINT_TYPE _type) { type = _type; } + void setState(USB_TYPE st) { state = st; } + void setDevice(USBDeviceConnected* _dev) { dev = _dev; } + void setBuffer(uint8_t* buf, int size) { buf_start = buf, buf_size = size; } + void setLengthTransferred(int len) { transferred = len; }; + void setAddress(int addr) { address = addr; } + void setSize(int size) { MaxPacketSize = size; } + void setData01(uint8_t data01) { data01_toggle = data01; } + void setNextEndpoint(USBEndpoint* ep) { nextEp = ep; }; + template<class T> + void setHALData(T data) { pData = data; } + + USBDeviceConnected* getDevice() { return dev; } + ENDPOINT_TYPE getType() { return type; }; + USB_TYPE getState() { return state; } + int getLengthTransferred() { return transferred; } + uint8_t *getBufStart() { return buf_start; } + int getBufSize() { return buf_size; } + uint8_t getAddress(){ return address; }; + int getSize() { return MaxPacketSize; } + ENDPOINT_DIRECTION getDir() { return dir; } + uint8_t getData01() { return data01_toggle; } + void toggleData01() { + data01_toggle = (data01_toggle == DATA0) ? DATA1 : DATA0; + } + USBEndpoint* nextEndpoint() { return nextEp; }; + template<class T> + T getHALData() { return reinterpret_cast<T>(pData); } + + struct { + uint8_t queueLimit; + uint8_t frameCount; // 1-8 + } ohci; +private: + USBEndpoint(){} + ENDPOINT_TYPE type; + USB_TYPE state; + ENDPOINT_DIRECTION dir; + USBDeviceConnected* dev; + uint8_t data01_toggle; // DATA0,DATA1 + uint8_t address; + int transferred; + uint8_t * buf_start; + int buf_size; + FunctionPointer rx; + int MaxPacketSize; + USBEndpoint* nextEp; + void* pData; +}; + +class EndpointQueue { +public: + EndpointQueue():head(NULL),tail(NULL) {} + void push(USBEndpoint* ep) { + if (head) { + tail->setNextEndpoint(ep); + } else { + head = ep; + } + tail = ep; + ep->setNextEndpoint(NULL); + } + USBEndpoint* pop() { + USBEndpoint* ep = head; + if (ep) { + head = ep->nextEndpoint(); + } + return ep; + } + bool empty() { return head == NULL; } + +private: + USBEndpoint* head; + USBEndpoint* tail; +}; + + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHALHost.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,35 @@ +#include "mbed.h" + +struct SETUP_PACKET { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + SETUP_PACKET(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) { + bmRequestType = RequestType; + bRequest = Request; + wValue = Value; + wIndex = Index; + wLength = Length; + } +}; + +#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE) +#include "USBHALHost_F401RE.h" +#elif defined(TARGET_KL46Z)||defined(TARGET_KL25Z)||defined(TARGET_K64F) +#include "USBHALHost_KL46Z.h" +#elif defined(TARGET_LPC4088)||defined(TARGET_LPC1768) +#include "USBHALHost_LPC4088.h" +#else +#error "target error" +#endif + +#ifndef CTASSERT +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); +#endif // CTASSERT + + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHALHost2_F401RE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost2_F401RE.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,540 @@ +#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE) +#include "USBHALHost.h" + +// usbh_conf.c +HCD_HandleTypeDef hhcd_USB_OTG_FS; + +static void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd); + +// stm32f4xx_it.c +extern "C" { +void OTG_FS_IRQHandler(void) +{ + HAL_NVIC_ClearPendingIRQ(OTG_FS_IRQn); + HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS); +} +} + +// stm32f4xx_hal_hcd.c +static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); +static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); +static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd); +static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd); + +/** + * @brief This function handles HCD interrupt request. + * @param hhcd: HCD handle + * @retval none + */ +static void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t i = 0 , interrupt = 0; + + /* ensure that we are in device mode */ + if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST) + { + /* avoid spurious interrupt */ + if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd)) + { + return; + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT); + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR); + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE); + } + + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS); + } + + /* Handle Host Disconnect Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT)) + { + + /* Cleanup HPRT */ + USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + /* Handle Host Port Interrupts */ + HAL_HCD_Disconnect_Callback(hhcd); + USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT); + } + + /* Handle Host Port Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT)) + { + HCD_Port_IRQHandler (hhcd); + } + + /* Handle Host SOF Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF)) + { + HAL_HCD_SOF_Callback(hhcd); + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF); + } + + /* Handle Host channel Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT)) + { + + interrupt = USB_HC_ReadInterrupt(hhcd->Instance); + for (i = 0; i < hhcd->Init.Host_channels ; i++) + { + if (interrupt & (1 << i)) + { + if ((USBx_HC(i)->HCCHAR) & USB_OTG_HCCHAR_EPDIR) + { + HCD_HC_IN_IRQHandler (hhcd, i); + } + else + { + HCD_HC_OUT_IRQHandler (hhcd, i); + } + } + } + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT); + } + + /* Handle Rx Queue Level Interrupts */ + if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) + { + USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); + + HCD_RXQLVL_IRQHandler (hhcd); + + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); + } + + } +} +/** + * @brief This function handles Host Channel IN interrupt requests. + * @param hhcd: HCD handle + * @param chnum : Channel number + * This parameter can be a value from 1 to 15 + * @retval none + */ +static void HCD_HC_IN_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + + if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR); + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + hhcd->hc[chnum].state = HC_STALL; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL); + USB_HC_Halt(hhcd->Instance, chnum); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + hhcd->hc[chnum].state = HC_DATATGLERR; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR); + } + + if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC) + { + + if (hhcd->Init.dma_enable) + { + hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \ + (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); + } + + hhcd->hc[chnum].state = HC_XFRC; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC); + + + if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)|| + (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + + } + else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR) + { + USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + } + else if(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC) + { + USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; + hhcd->hc[chnum].urb_state = URB_DONE; + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); + } + hhcd->hc[chnum].toggle_in ^= 1; + + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH) + { + __HAL_HCD_MASK_HALT_HC_INT(chnum); + + if(hhcd->hc[chnum].state == HC_XFRC) + { + hhcd->hc[chnum].urb_state = URB_DONE; + } + + else if (hhcd->hc[chnum].state == HC_NAK) + { + hhcd->hc[chnum].urb_state = URB_DONE; + } + + else if (hhcd->hc[chnum].state == HC_STALL) + { + hhcd->hc[chnum].urb_state = URB_STALL; + } + + else if (hhcd->hc[chnum].state == HC_XACTERR) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + + else if (hhcd->hc[chnum].state == HC_DATATGLERR) + { + hhcd->hc[chnum].urb_state = URB_ERROR; + } + + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + hhcd->hc[chnum].state = HC_XACTERR; + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK) + { + if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + } + else if (hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) + { + /* re-activate the channel */ + USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; + USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + + } + + else if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + } + + hhcd->hc[chnum].state = HC_NAK; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + } +} + +/** + * @brief This function handles Host Channel OUT interrupt requests. + * @param hhcd: HCD handle + * @param chnum : Channel number + * This parameter can be a value from 1 to 15 + * @retval none + */ +static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + + if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR); + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + } + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK); + + if( hhcd->hc[chnum].do_ping == 1) + { + hhcd->hc[chnum].state = HC_NYET; + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NYET) + { + hhcd->hc[chnum].state = HC_NYET; + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET); + + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC); + hhcd->hc[chnum].state = HC_XFRC; + + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL) + { + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL); + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].state = HC_STALL; + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].state = HC_NAK; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + hhcd->hc[chnum].state = HC_XACTERR; + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR); + } + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR) + { + __HAL_HCD_UNMASK_HALT_HC_INT(chnum); + USB_HC_Halt(hhcd->Instance, chnum); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR); + hhcd->hc[chnum].state = HC_DATATGLERR; + } + + + else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH) + { + __HAL_HCD_MASK_HALT_HC_INT(chnum); + + if(hhcd->hc[chnum].state == HC_XFRC) + { + hhcd->hc[chnum].urb_state = URB_DONE; + if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK) + { + hhcd->hc[chnum].toggle_out ^= 1; + } + } + else if (hhcd->hc[chnum].state == HC_NAK) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + + else if (hhcd->hc[chnum].state == HC_NYET) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + hhcd->hc[chnum].do_ping = 0; + } + + else if (hhcd->hc[chnum].state == HC_STALL) + { + hhcd->hc[chnum].urb_state = URB_STALL; + } + + else if(hhcd->hc[chnum].state == HC_XACTERR) + { + hhcd->hc[chnum].urb_state = URB_NOTREADY; + } + + else if (hhcd->hc[chnum].state == HC_DATATGLERR) + { + hhcd->hc[chnum].urb_state = URB_ERROR; + } + + __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); + } +} + +/** + * @brief This function handles Rx Queue Level interrupt requests. + * @param hhcd: HCD handle + * @retval none + */ +static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint8_t channelnum =0; + uint32_t pktsts; + uint32_t pktcnt; + uint32_t temp = 0; + + temp = hhcd->Instance->GRXSTSP ; + channelnum = temp & USB_OTG_GRXSTSP_EPNUM; + pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17; + pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + + switch (pktsts) + { + case GRXSTS_PKTSTS_IN: + /* Read the data into the host buffer. */ + if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void *)0)) + { + + USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt); + + /*manage multiple Xfer */ + hhcd->hc[channelnum].xfer_buff += pktcnt; + hhcd->hc[channelnum].xfer_count += pktcnt; + + if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0) + { + /* re-activate the channel when more packets are expected */ + USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; + USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + hhcd->hc[channelnum].toggle_in ^= 1; + } + } + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + break; + case GRXSTS_PKTSTS_IN_XFER_COMP: + case GRXSTS_PKTSTS_CH_HALTED: + default: + break; + } +} + +/** + * @brief This function handles Host Port interrupt requests. + * @param hhcd: HCD handle + * @retval none + */ +static void HCD_Port_IRQHandler (HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + __IO uint32_t hprt0, hprt0_dup; + + /* Handle Host Port Interrupts */ + hprt0 = USBx_HPRT0; + hprt0_dup = USBx_HPRT0; + + hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + /* Check wether Port Connect Detected */ + if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) + { + if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) + { + USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); + HAL_HCD_Connect_Callback(hhcd); + } + hprt0_dup |= USB_OTG_HPRT_PCDET; + + } + + /* Check whether Port Enable Changed */ + if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) + { + hprt0_dup |= USB_OTG_HPRT_PENCHNG; + + if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) + { + if(hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY) + { + if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) + { + USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ ); + } + else + { + USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); + } + } + else + { + if(hhcd->Init.speed == HCD_SPEED_FULL) + { + USBx_HOST->HFIR = (uint32_t)60000; + } + } + HAL_HCD_Connect_Callback(hhcd); + + if(hhcd->Init.speed == HCD_SPEED_HIGH) + { + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); + } + } + else + { + /* Cleanup HPRT */ + USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); + } + } + + /* Check For an overcurrent */ + if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) + { + hprt0_dup |= USB_OTG_HPRT_POCCHNG; + } + + /* Clear Port Interrupts */ + USBx_HPRT0 = hprt0_dup; +} + +#endif + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHALHost_F401RE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,534 @@ +#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE) +#include "USBHALHost.h" +#include <algorithm> + +#ifdef _USB_DBG +extern RawSerial pc; +//RawSerial pc(USBTX,USBRX); +#include "mydebug.h" +#define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0); +#define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B) + +#else +#define USB_DBG(...) while(0) +#define USB_DBG_HEX(A,B) while(0) +#endif + +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + +#define USB_TRACE1(A) while(0) + +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + +__IO bool attach_done = false; + +void delay_ms(uint32_t t) +{ + HAL_Delay(t); +} + +// usbh_conf.c +extern HCD_HandleTypeDef hhcd_USB_OTG_FS; + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if(hhcd->Instance==USB_OTG_FS) + { + /* Peripheral clock enable */ + __USB_OTG_FS_CLK_ENABLE(); + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral interrupt init*/ + /* Sets the priority grouping field */ + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0); + HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +} + +// stm32f4xx_it.c +extern "C" { +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USB_TRACE1(hhcd); + attach_done = true; +} + +} // extern "C" + +USBHALHost* USBHALHost::instHost; + +USBHALHost::USBHALHost() { + instHost = this; +} + +void USBHALHost::init() { + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE; + hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE; + hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE; + + HAL_HCD_Init(&hhcd_USB_OTG_FS); + HAL_HCD_Start(&hhcd_USB_OTG_FS); + + bool lowSpeed = wait_attach(); + delay_ms(200); + HAL_HCD_ResetPort(&hhcd_USB_OTG_FS); + delay_ms(100); // Wait for 100 ms after Reset + addDevice(NULL, 0, lowSpeed); +} + +bool USBHALHost::wait_attach() { + Timer t; + t.reset(); + t.start(); + while(!attach_done) { + if (t.read_ms() > 5*1000) { + t.reset(); + USB_INFO("Please attach USB device."); + } + } + wait_ms(100); + return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW; +} + +int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { + const uint8_t ep_addr = 0x00; + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + setup->wLength = wLength; + hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + break; + } + ep->setData01(DATA1); + return 8; +} + +int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + switch(ep->getType()) { + case CONTROL_ENDPOINT: + return token_ctl_in(ep, data, size, retryLimit); + case INTERRUPT_ENDPOINT: + return token_int_in(ep, data, size); + case BULK_ENDPOINT: + return token_blk_in(ep, data, size, retryLimit); + } + return -1; +} + +int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + const uint8_t ep_addr = 0x80; + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + return -1; + } + ep->toggleData01(); + return hc.GetXferCount(); +} + +int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + switch(hc.GetURBState()) { + case URB_DONE: + switch(hc.GetState()) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return hc.GetXferCount(); + case HC_NAK: + LastStatus = NAK; + return -1; + } + break; + } + LastStatus = STALL; + return -1; +} + +int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_BULK, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + int retry = 0; + do { + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + switch(hc.GetState()) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return hc.GetXferCount(); + case HC_NAK: + LastStatus = NAK; + if (retryLimit > 0) { + delay_ms(1 + 10 * retry); + } + break; + default: + break; + } + break; + case URB_STALL: + LastStatus = STALL; + return -1; + default: + LastStatus = STALL; + delay_ms(500 + 100 * retry); + break; + } + }while(retry++ < retryLimit); + return -1; +} + +int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + switch(ep->getType()) { + case CONTROL_ENDPOINT: + return token_ctl_out(ep, data, size, retryLimit); + case INTERRUPT_ENDPOINT: + return token_int_out(ep, data, size); + case BULK_ENDPOINT: + return token_blk_out(ep, data, size, retryLimit); + } + return -1; +} + +int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + const uint8_t ep_addr = 0x00; + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + do { + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + LastStatus = ACK; + ep->toggleData01(); + return size; + + default: + break; + } + delay_ms(1); + }while(retryLimit-- > 0); + return -1; +} + +int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + if (hc.GetURBState() != URB_DONE) { + return -1; + } + ep->toggleData01(); + return size; +} + +int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + HC hc; + USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + + int retry = 0; + do { + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + + switch(hc.GetURBState()) { + case URB_DONE: + switch(hc.GetState()) { + case HC_XFRC: // ACK + LastStatus = ep->getData01(); + ep->toggleData01(); + return size; + default: + break; + } + break; + case URB_NOTREADY: // HC_NAK + LastStatus = NAK; + delay_ms(100 * retry); + break; + default: + LastStatus = STALL; + return -1; + } + } while(retry++ < retryLimit); + return -1; +} + +int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { + HC* hc = ep->getHALData<HC*>(); + if (hc == NULL) { + hc = new HC; + ep->setHALData<HC*>(hc); + USBDeviceConnected* dev = ep->getDevice(); + hc->Init( + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize()); + } + hc->SubmitRequest(data, size); + while(hc->GetURBState() == URB_IDLE); + return hc->GetXferCount(); +} + +int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) { + if (total == 0) { + return token_in(ep); + } + int retryLimit = block ? 10 : 0; + int read_len = 0; + for(int n = 0; read_len < total; n++) { + int size = std::min((int)total-read_len, ep->getSize()); + int result = token_in(ep, data+read_len, size, retryLimit); + if (result < 0) { + if (block) { + return -1; + } + if (LastStatus == NAK) { + if (n == 0) { + return -1; + } + break; + } + return result; + } + read_len += result; + if (result < ep->getSize()) { + break; + } + } + return read_len; +} + +int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) { + if (total == 0) { + return token_out(ep); + } + int write_len = 0; + for(int n = 0; write_len < total; n++) { + int size = std::min((int)total-write_len, ep->getSize()); + int result = token_out(ep, data+write_len, size); + if (result < 0) { + if (LastStatus == NAK) { + if (n == 0) { + return -1; + } + break; + } + USB_DBG("token_out result=%d %02x", result, LastStatus); + return result; + } + write_len += result; + if (result < ep->getSize()) { + break; + } + } + return write_len; +} +void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + ep->setState(USB_TYPE_PROCESSING); +} + +USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) { + USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING); + uint8_t* buf = ep->getBufStart(); + int size = ep->getBufSize(); + int result = multi_token_in(ep, buf, size, false); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_PROCESSING; + } + ep->setLengthTransferred(result); + ep->setState(USB_TYPE_IDLE); + return USB_TYPE_OK; + +} + +void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) { + USB_TEST_ASSERT(toggle == 1); + ep->setData01(toggle == 0 ? DATA0 : DATA1); +} + +uint8_t HC::slot = 0x00; + +HC::HC() { + static const int start = 1; + uint8_t mask = (1<<start); + for(int i = start; i < 8; i++, mask <<= 1) { + if (!(slot & mask)) { + slot |= mask; + _ch = i; + return; + } + } + _ch = 0; // ERROR!!! +} + +HC::HC(int ch) { + _ch = ch; + slot |= (1<<_ch); +} + +HC::~HC() { + slot &= ~(1<<_ch); +} + +HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) { + _ep_addr = epnum; + _ep_type = ep_type; + return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch, + epnum, dev_address, speed, ep_type, mps); +} + +HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) { + uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT; + if (_ep_type == EP_TYPE_CTRL) { + HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch]; + if (setup) { + hc->data_pid = HC_PID_SETUP; + hc->toggle_out = 0; + } else { + if (direction == DIR_IN) { + if (hc->toggle_in == 0) { + hc->data_pid = HC_PID_DATA0; + } else { + hc->data_pid = HC_PID_DATA1; + } + } else { // OUT + if (hc->toggle_out == 0) { + hc->data_pid = HC_PID_DATA0; + } else { + hc->data_pid = HC_PID_DATA1; + } + } + } + hc->xfer_buff = pbuff; + hc->xfer_len = length; + hc->urb_state = URB_IDLE; + hc->xfer_count = 0; + hc->ch_num = _ch; + hc->state = HC_IDLE; + + return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0); + } + return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch, + direction, _ep_type, 0, pbuff, length, 0); +} + +HCD_URBStateTypeDef HC::GetURBState() { + return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch); +} + +HCD_HCStateTypeDef HC::GetState() { + return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch); +} + +uint32_t HC::GetXferCount() { + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch); +} + +void HC::SetToggle(uint8_t toggle) { + if (_ep_addr & 0x80) { // IN + hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle; + } else { // OUT + hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle; + } +} + +#endif + + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHALHost_F401RE.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,59 @@ +#pragma once +#include "mbed.h" +#include "USBHostTypes.h" +#include "USBEndpoint.h" + +class HC { + static const uint8_t DIR_IN = 1; + static const uint8_t DIR_OUT = 0; + +public: + HC(); + HC(int ch); + ~HC(); + HAL_StatusTypeDef Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps); + HAL_StatusTypeDef SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup = false); + HCD_URBStateTypeDef GetURBState(); + HCD_HCStateTypeDef GetState(); + uint32_t GetXferCount(); + void SetToggle(uint8_t toggle); + + static uint8_t slot; + +private: + int _ch; + uint8_t _ep_addr; + uint8_t _ep_type; +}; + +class USBHALHost { +public: + uint8_t LastStatus; + uint8_t prev_LastStatus; + +protected: + USBHALHost(); + void init(); + virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0; + int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0); + int token_iso_in(USBEndpoint* ep, uint8_t* data, int size); + int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, size_t total = 0, bool block = true); + int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0); + void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size); + USB_TYPE multi_token_inNB_result(USBEndpoint* ep); + void setToggle(USBEndpoint* ep, uint8_t toggle); + +private: + int token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10); + int token_out(USBEndpoint* ep, const uint8_t* data = NULL, int size = 0, int retryLimit = 10); + int token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit); + int token_int_in(USBEndpoint* ep, uint8_t* data, int size); + int token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit); + int token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit); + int token_int_out(USBEndpoint* ep, const uint8_t* data, int size); + int token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit); + bool wait_attach(); + static USBHALHost * instHost; +}; + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHost.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHost.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,352 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "USBHost.h" + +#define USB_TRACE1(A) while(0) +#undef USB_TEST_ASSERT +void usb_test_assert_internal(const char *expr, const char *file, int line); +#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} + +USBHost* USBHost::inst = NULL; + +USBHost* USBHost::getHostInst() { + if (inst == NULL) { + inst = new USBHost(); + inst->init(); + } + return inst; +} + +void USBHost::poll() +{ + if (inst) { + inst->task(); + } +} + +USBHost::USBHost() { +} + +/* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) { + USBDeviceConnected* dev = new USBDeviceConnected; + USBEndpoint* ep = new USBEndpoint(dev); + dev->init(0, port, lowSpeed); + dev->setAddress(0); + dev->setEpCtl(ep); + uint8_t desc[18]; + wait_ms(100); + + int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + if (rc != USB_TYPE_OK) { + USB_ERR("ADD DEVICE FAILD"); + } + USB_DBG_HEX(desc, 8); + DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); + ep->setSize(dev_desc->bMaxPacketSize); + + int new_addr = USBDeviceConnected::getNewAddress(); + rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + dev->setAddress(new_addr); + wait_ms(100); + + rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + USB_DBG_HEX(desc, sizeof(desc)); + + dev->setVid(dev_desc->idVendor); + dev->setPid(dev_desc->idProduct); + dev->setClass(dev_desc->bDeviceClass); + USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d", + parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), + dev->getAddress()); + + DeviceLists.push_back(dev); + + if (dev->getClass() == HUB_CLASS) { + const int config = 1; + int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + wait_ms(100); + Hub(dev); + } + return true; +} + +// enumerate a device with the control USBEndpoint +USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) +{ + if (dev->getClass() == HUB_CLASS) { // skip hub class + return USB_TYPE_OK; + } + uint8_t desc[18]; + USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + USB_DBG_HEX(desc, sizeof(desc)); + if (rc != USB_TYPE_OK) { + return rc; + } + DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); + dev->setClass(dev_desc->bDeviceClass); + pEnumerator->setVidPid(dev->getVid(), dev->getPid()); + + rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + USB_DBG_HEX(desc, 4); + + int TotalLength = desc[2]|desc[3]<<8; + uint8_t* buf = new uint8_t[TotalLength]; + rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + //USB_DBG_HEX(buf, TotalLength); + + // Parse the configuration descriptor + parseConfDescr(dev, buf, TotalLength, pEnumerator); + delete[] buf; + // only set configuration if not enumerated before + if (!dev->isEnumerated()) { + USB_DBG("Set configuration 1 on dev: %p", dev); + // sixth step: set configuration (only 1 supported) + int config = 1; + USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); + if (res != USB_TYPE_OK) { + USB_ERR("SET CONF FAILED"); + return res; + } + // Some devices may require this delay + wait_ms(100); + dev->setEnumerated(); + // Now the device is enumerated! + USB_DBG("dev %p is enumerated", dev); + } + return USB_TYPE_OK; +} + +// this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. +void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) +{ + uint32_t index = 0; + uint32_t len_desc = 0; + uint8_t id = 0; + USBEndpoint * ep = NULL; + uint8_t intf_nb = 0; + bool parsing_intf = false; + uint8_t current_intf = 0; + EndpointDescriptor* ep_desc; + + while (index < len) { + len_desc = conf_descr[index]; + id = conf_descr[index+1]; + USB_DBG_HEX(conf_descr+index, len_desc); + switch (id) { + case CONFIGURATION_DESCRIPTOR: + USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); + dev->setNbIntf(conf_descr[4]); + break; + case INTERFACE_DESCRIPTOR: + if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { + intf_nb++; + current_intf = conf_descr[index + 2]; + dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); + USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); + parsing_intf = true; + } else { + parsing_intf = false; + } + break; + case ENDPOINT_DESCRIPTOR: + ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); + if (parsing_intf && (intf_nb <= MAX_INTF) ) { + ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); + ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; + if(pEnumerator->useEndpoint(current_intf, type, dir)) { + ep = new USBEndpoint(dev); + ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress); + USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); + dev->addEndpoint(current_intf, ep); + } + } + break; + case HID_DESCRIPTOR: + //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); + break; + default: + break; + } + index += len_desc; + } +} + +USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { + USBEndpoint* ep = dev->getEpCtl(); + SETUP_PACKET setup(requestType, request, value, index, len); + + int result = token_setup(ep, &setup, len); // setup stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + + int read_len = multi_token_in(ep, buf, len); // data stage + USB_TRACE1(read_len); + if (read_len < 0) { + return USB_TYPE_ERROR; + } + + setToggle(ep, 1); // DATA1 + result = multi_token_out(ep); // status stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(read_len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { + USBEndpoint* ep = dev->getEpCtl(); + SETUP_PACKET setup(requestType, request, value, index, len); + + int result = token_setup(ep, &setup, len); // setup stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + int write_len = 0; + if (buf != NULL) { + write_len = multi_token_out(ep, buf, len); // data stage + USB_TRACE1(write_len); + if (write_len < 0) { + return USB_TYPE_ERROR; + } + } + + setToggle(ep, 1); // DATA1 + result = multi_token_in(ep); // status stage + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(write_len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setBuffer(buf, len); + ep_queue.push(ep); + multi_token_inNB(ep, buf, len); + return USB_TYPE_PROCESSING; + } + int result = multi_token_in(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + int result = multi_token_out(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setBuffer(buf, len); + ep_queue.push(ep); + multi_token_inNB(ep, buf, len); + return USB_TYPE_PROCESSING; + } + int result = multi_token_in(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + int result = multi_token_out(ep, buf, len); + USB_TRACE1(result); + if (result < 0) { + return USB_TYPE_ERROR; + } + ep->setLengthTransferred(result); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + isochronousReadNB(ep, buf, len); + return USB_TYPE_OK; +} + +int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + if (ep->getState() != USB_TYPE_PROCESSING) { + ep->setState(USB_TYPE_PROCESSING); + ep->setBuffer(data, size); + multi_token_inNB(ep, data, size); + } + if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { + return ep->getLengthTransferred(); + } + return -1; +} + +int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + return interruptReadNB(ep, data, size); +} + +int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { + USB_TRACE1(size); + int result = token_iso_in(ep, data, size); + if (result >= 0) { + ep->setLengthTransferred(result); + } + return result; +} + +void USBHost::task() { + USBEndpoint* ep = ep_queue.pop(); + if (ep) { + USB_TEST_ASSERT(ep->getDir() == IN); + if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { + ep->call(); + } else { + ep_queue.push(ep); + } + } +} + +void usb_test_assert_internal(const char *expr, const char *file, int line){ + error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr); +} + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHost.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHost.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,195 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include "mbed.h" +#include "USBHALHost.h" +#include "USBDeviceConnected.h" +#include "IUSBEnumerator.h" +#include "USBHostConf.h" +#include "dbg.h" +#include "myvector.h" + +/** +* USBHost class +* This class is a singleton. All drivers have a reference on the static USBHost instance +*/ +class USBHost : public USBHALHost { +public: + /** + * Static method to create or retrieve the single USBHost instance + */ + static USBHost* getHostInst(); + + /** + * Control read: setup stage, data stage and status stage + * + * @param dev the control read will be done for this device + * @param requestType request type + * @param request request + * @param value value + * @param index index + * @param buf pointer on a buffer where will be store the data received + * @param len length of the transfer + * + * @returns status of the control read + */ + USB_TYPE controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len); + + /** + * Control write: setup stage, data stage and status stage + * + * @param dev the control write will be done for this device + * @param requestType request type + * @param request request + * @param value value + * @param index index + * @param buf pointer on a buffer which will be written + * @param len length of the transfer + * + * @returns status of the control write + */ + USB_TYPE controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len); + + /** + * Bulk read + * + * @param dev the bulk transfer will be done for this device + * @param ep USBEndpoint which will be used to read a packet + * @param buf pointer on a buffer where will be store the data received + * @param len length of the transfer + * @param blocking if true, the read is blocking (wait for completion) + * + * @returns status of the bulk read + */ + USB_TYPE bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); + + /** + * Bulk write + * + * @param dev the bulk transfer will be done for this device + * @param ep USBEndpoint which will be used to write a packet + * @param buf pointer on a buffer which will be written + * @param len length of the transfer + * @param blocking if true, the write is blocking (wait for completion) + * + * @returns status of the bulk write + */ + USB_TYPE bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); + + /** + * Interrupt read + * + * @param dev the interrupt transfer will be done for this device + * @param ep USBEndpoint which will be used to write a packet + * @param buf pointer on a buffer which will be written + * @param len length of the transfer + * @param blocking if true, the read is blocking (wait for completion) + * + * @returns status of the interrupt read + */ + USB_TYPE interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); + + /** + * Interrupt write + * + * @param dev the interrupt transfer will be done for this device + * @param ep USBEndpoint which will be used to write a packet + * @param buf pointer on a buffer which will be written + * @param len length of the transfer + * @param blocking if true, the write is blocking (wait for completion) + * + * @returns status of the interrupt write + */ + USB_TYPE interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true); + + /** + * Isochronous read + * + * @param dev the isochronous transfer will be done for this device + * @param ep USBEndpoint which will be used to write a packet + * @param buf pointer on a buffer which will be written + * @param len length of the transfer + * @param blocking if true, the read is blocking (wait for completion) + * + * @returns status of the interrupt read + */ + USB_TYPE isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking = true); + + /** + * Enumerate a device. + * + * @param dev device which will be enumerated + * + * @returns status of the enumeration + */ + USB_TYPE enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator); + + /** + * Get a device + * + * @param index index of the device which will be returned + * + * @returns pointer on the "index" device + */ + USBDeviceConnected * getDevice(uint8_t index) { + return index < DeviceLists.size() ? DeviceLists[index] : NULL; + } + + /** + * register a driver into the host associated with a callback function called when the device is disconnected + * + * @param dev device + * @param intf interface number + * @param tptr pointer to the object to call the member function on + * @param mptr pointer to the member function to be called + */ + template<typename T> + void registerDriver(USBDeviceConnected * dev, uint8_t intf, T* tptr, void (T::*mptr)(void)) { + } + + // KL46Z-USBHost extensions + int interruptReadNB(USBEndpoint* ep, uint8_t* data, int size); + int bulkReadNB(USBEndpoint*ep, uint8_t* data, int size); + int isochronousReadNB(USBEndpoint*ep, uint8_t* data, int size); + + /** + * non-blocking processing + */ + static void poll(); + +private: + USBHost(); + static USBHost* inst; + virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed); + void root_enumeration(USBDeviceConnected* dev); + void parseConfDescr(USBDeviceConnected* dev, uint8_t* conf_descr, uint32_t len, IUSBEnumerator* pEnumerator); + myvector<USBDeviceConnected*>DeviceLists; + void task(); + EndpointQueue ep_queue; + + // USB HUB + bool Hub(USBDeviceConnected* dev); + int SetPortPower(USBDeviceConnected* dev, int port); + int ClearPortPower(USBDeviceConnected* dev, int port); + int PortReset(USBDeviceConnected* dev, int port); + int SetPortFeature(USBDeviceConnected* dev, int feature, int index); + int ClearPortFeature(USBDeviceConnected* dev, int feature, int index); + int SetPortReset(USBDeviceConnected* dev, int port); + int GetPortStatus(USBDeviceConnected* dev, int port, uint32_t* status); +}; + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHostConf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostConf.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,72 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USBHOST_CONF_H +#define USBHOST_CONF_H + +/* +* Maximum number of devices that can be connected +* to the usb host +*/ +#define MAX_DEVICE_CONNECTED 5 + +/* +* Maximum of Hub connected to the usb host +*/ +#define MAX_HUB_NB 1 + +/* +* Maximum number of ports on a USB hub +*/ +#define MAX_HUB_PORT 4 + +/* +* Enable USBHostMSD +*/ +#define USBHOST_MSD 0 + +/* +* Enable USBHostKeyboard +*/ +#define USBHOST_KEYBOARD 0 + +/* +* Enable USBHostMouse +*/ +#define USBHOST_MOUSE 0 + +/* +* Enable USBHostSerial or USBHostMultiSerial (if set > 1) +*/ +#define USBHOST_SERIAL 0 + +/* +* Enable USB3Gmodule +*/ +#define USBHOST_3GMODULE 0 + +/* +* Maximum number of interfaces of a usb device +*/ +#define MAX_INTF 4 + +/* +* usb_thread stack size +*/ +#define USB_THREAD_STACK (256*4 + MAX_HUB_NB*256*4) + +#endif +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHostGamepad.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostGamepad.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,119 @@ +/* + * mbed USBHost Gamepad driver sample + * Copyright (c) 2014 Yuuichi Akagawa + * + * modified from mbed USBHostMouse + * + * mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "USBHostGamepad.h" +//#if USBHOST_GAMEPAD + +USBHostGamepad::USBHostGamepad() { + host = USBHost::getHostInst(); + init(); +} + +void USBHostGamepad::init() { + dev = NULL; + int_in = NULL; + dev_connected = false; + gamepad_device_found = false; + gamepad_intf = -1; +} + +bool USBHostGamepad::connected() { + return dev_connected; +} + +bool USBHostGamepad::connect() { + if (dev_connected) { + return true; + } + + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { + if ((dev = host->getDevice(i)) != NULL) { + + if(host->enumerate(dev, this)) + break; + + if (gamepad_device_found) { + + int_in = dev->getEndpoint(gamepad_intf, INTERRUPT_ENDPOINT, IN); + if (!int_in) + break; + + USB_INFO("New Gamepad/Joystick device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gamepad_intf); +#if DEBUG > 3 + //Parse HID Report Descriptor + parseHidDescr(); +#endif + dev->setName("Gamepad", gamepad_intf); + host->registerDriver(dev, gamepad_intf, this, &USBHostGamepad::init); + + int_in->attach(this, &USBHostGamepad::rxHandler); + rxSize = int_in->getSize(); + if (rxSize > sizeof(report)) + rxSize = sizeof(report); + host->interruptRead(dev, int_in, report, rxSize, false); + + dev_connected = true; + return true; + } + } + } + init(); + return false; +} + +void USBHostGamepad::rxHandler() { + if (dev) + host->interruptRead(dev, int_in, report, rxSize, false); + + /* modified 2016 Racoon */ + +} + +/*virtual*/ void USBHostGamepad::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for gamepad driver +} + +/*virtual*/ bool USBHostGamepad::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + if ((gamepad_intf == -1) && + (intf_class == HID_CLASS) && + (intf_subclass == 0x00) && + (intf_protocol == 0x00)) { + gamepad_intf = intf_nb; + return true; + } + return false; +} + +/*virtual*/ bool USBHostGamepad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (intf_nb == gamepad_intf) { + if (type == INTERRUPT_ENDPOINT && dir == IN) { + gamepad_device_found = true; + return true; + } + } + return false; +} + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHostGamepad.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostGamepad.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,90 @@ +/* + * modified from + * mbed USBHost Gamepad driver sample + * Copyright (c) 2014 Yuuichi Akagawa + * + * modified from mbed USBHostMouse + * + * Copyright (c) 2014 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef USBHOSTGAMEPAD_H +#define USBHOSTGAMEPAD_H + +#include "USBHostConf.h" + +//#if USBHOST_GAMEPAD + +#include "USBHost.h" +//HID Class Request +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_GET_DESCRIPTOR 0x06 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0a +#define HID_SET_PROTOCOL 0x0b + +/** + * A class to communicate a USB MIDI device + */ +class USBHostGamepad : public IUSBEnumerator { +public: + /** + * Constructor + */ + USBHostGamepad(); + + /** + * Try to connect a gamepad device + * + * @return true if connection was successful + */ + bool connect(); + + /** + * Check if a gamepad is connected + * + * @returns true if a gamepad is connected + */ + bool connected(); + + uint8_t report[8]; /* modified 2016 Racoon */ + int rxSize; + +protected: + //From IUSBEnumerator + virtual void setVidPid(uint16_t vid, uint16_t pid); + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used + +private: + USBHost * host; + USBDeviceConnected * dev; + USBEndpoint * int_in; + + bool dev_connected; + bool gamepad_device_found; + int gamepad_intf; + + void rxHandler(); + void init(); +}; + +#endif +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHostHub.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostHub.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,113 @@ +#include "USBHost.h" + +#define PORT_CONNECTION 0 +#define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 +#define PORT_RESET 4 +#define PORT_POWER 8 +#define PORT_LOW_SPEED 9 + +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 + +bool USBHost::Hub(USBDeviceConnected* dev) { + USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev); + HubDescriptor hubdesc; + // get HUB descriptor + int rc = controlRead(dev, + USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, + GET_DESCRIPTOR, + 0x29 << 8, 0, reinterpret_cast<uint8_t*>(&hubdesc), + sizeof(HubDescriptor)); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + if (rc != USB_TYPE_OK) { + return false; + } + USB_DBG_HEX((uint8_t*)&hubdesc, sizeof(hubdesc)); + + uint32_t status; + rc = controlRead( dev, + 0xa0, 0, 0, 0, reinterpret_cast<uint8_t*>(&status), 4); + USB_TEST_ASSERT(rc == USB_TYPE_OK); + if (rc != USB_TYPE_OK) { + return false; + } + USB_DBG("HUB STATUS: %08X\n", status); + + for(int i = 1; i <= hubdesc.bNbrPorts; i++) { + SetPortPower(dev, i); // power on + wait_ms(hubdesc.bPwrOn2PwrGood*2); + uint32_t status; + GetPortStatus(dev, i, &status); + USB_DBG("port: %d status: %08X\n", i, status); + if (status & 0x010000) { // Connect Status Change, has changed + USB_TEST_ASSERT(status & 0x000001); + ClearPortFeature(dev, C_PORT_CONNECTION, i); + int lowSpeed = 0; + if (status & 0x0200) { + lowSpeed = 1; + } + PortReset(dev, i); + if (!addDevice(dev, i, lowSpeed)) { + ClearPortPower(dev, i); // power off + } + } else { + ClearPortPower(dev, i); // power off + } + } + return false; +} + + +int USBHost::SetPortPower(USBDeviceConnected* dev, int port) +{ + return SetPortFeature(dev, PORT_POWER, port); +} + +int USBHost::ClearPortPower(USBDeviceConnected* dev, int port) +{ + return ClearPortFeature(dev, PORT_POWER, port); +} + +int USBHost::SetPortFeature(USBDeviceConnected* dev, int feature, int index) +{ + return controlWrite(dev, 0x23, SET_FEATURE,feature,index,0,0); +} + +int USBHost::ClearPortFeature(USBDeviceConnected* dev, int feature, int index) +{ + return controlWrite(dev, 0x23, CLEAR_FEATURE,feature,index,0,0); +} + +int USBHost::SetPortReset(USBDeviceConnected* dev, int port) +{ + return SetPortFeature(dev, PORT_RESET, port); +} + +int USBHost::GetPortStatus(USBDeviceConnected* dev, int port, uint32_t* status) +{ + return controlRead(dev, 0xa3, GET_STATUS, 0, port, (uint8_t*)status, 4); +} + +int USBHost::PortReset(USBDeviceConnected* dev, int port) +{ + USB_DBG("%p port=%d\n", this, port); + USB_TEST_ASSERT(port >= 1); + SetPortReset(dev, port); + // wait reset + for(int i = 0; i < 100; i++) { + uint32_t status; + GetPortStatus(dev, port, &status); + USB_DBG("RESET port: %d status: %08X\n", port, status); + if (status & 0x100000) { // Reset change , Reset complete + return USB_TYPE_OK; + } + wait_ms(5); + } + return USB_TYPE_ERROR; +} +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/USBHostTypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHostTypes.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,168 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USB_INC_H +#define USB_INC_H + +#include "mbed.h" +#include "toolchain.h" + +enum USB_TYPE { + USB_TYPE_OK = 0, + + // completion code + USB_TYPE_CRC_ERROR = 1, + USB_TYPE_BIT_STUFFING_ERROR = 2, + USB_TYPE_DATA_TOGGLE_MISMATCH_ERROR = 3, + USB_TYPE_STALL_ERROR = 4, + USB_TYPE_DEVICE_NOT_RESPONDING_ERROR = 5, + USB_TYPE_PID_CHECK_FAILURE_ERROR = 6, + USB_TYPE_UNEXPECTED_PID_ERROR = 7, + USB_TYPE_DATA_OVERRUN_ERROR = 8, + USB_TYPE_DATA_UNDERRUN_ERROR = 9, + USB_TYPE_RESERVED = 9, + USB_TYPE_RESERVED_ = 10, + USB_TYPE_BUFFER_OVERRUN_ERROR = 12, + USB_TYPE_BUFFER_UNDERRUN_ERROR = 13, + + // general usb state + USB_TYPE_DISCONNECTED = 14, + USB_TYPE_FREE = 15, + USB_TYPE_IDLE = 16, + USB_TYPE_PROCESSING = 17, + + USB_TYPE_ERROR = 18, +}; + + +enum ENDPOINT_DIRECTION { + OUT = 1, + IN +}; + +enum ENDPOINT_TYPE { + CONTROL_ENDPOINT = 0, + ISOCHRONOUS_ENDPOINT, + BULK_ENDPOINT, + INTERRUPT_ENDPOINT +}; + +#define AUDIO_CLASS 0x01 +#define CDC_CLASS 0x02 +#define HID_CLASS 0x03 +#define MSD_CLASS 0x08 +#define HUB_CLASS 0x09 +#define SERIAL_CLASS 0x0A + +#define DEVICE_DESCRIPTOR (1) +#define CONFIGURATION_DESCRIPTOR (2) +#define INTERFACE_DESCRIPTOR (4) +#define ENDPOINT_DESCRIPTOR (5) +#define HID_DESCRIPTOR (33) + +// ----------- Control RequestType Fields ----------- +#define USB_DEVICE_TO_HOST 0x80 +#define USB_HOST_TO_DEVICE 0x00 +#define USB_REQUEST_TYPE_CLASS 0x20 +#define USB_REQUEST_TYPE_STANDARD 0x00 +#define USB_RECIPIENT_DEVICE 0x00 +#define USB_RECIPIENT_INTERFACE 0x01 +#define USB_RECIPIENT_ENDPOINT 0x02 + +// -------------- USB Standard Requests -------------- +#define GET_STATUS 0x00 +#define SET_FEATURE 0x03 +#define SET_ADDRESS 0x05 +#define GET_DESCRIPTOR 0x06 +#define SET_CONFIGURATION 0x09 +#define SET_INTERFACE 0x0b +#define CLEAR_FEATURE 0x01 + +// -------------- USB Descriptor Length -------------- +#define DEVICE_DESCRIPTOR_LENGTH 0x12 +#define CONFIGURATION_DESCRIPTOR_LENGTH 0x09 + +// PID +#define DATA0 0x03 +#define DATA1 0x0b +#define ACK 0x02 +#define STALL 0x0e +#define NAK 0x0a + +#pragma pack(push,1) +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} PACKED DeviceDescriptor; + +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} PACKED ConfigurationDescriptor; + +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} InterfaceDescriptor; + +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} EndpointDescriptor; + +typedef struct { + uint8_t bDescLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPweCtrlMak; +} HubDescriptor; +#pragma pack(pop) + +#endif +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/dbg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/dbg.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,91 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef USB_DEBUG_H +#define USB_DEBUG_H + +//Debug is disabled by default +#ifndef DEBUG +//#define DEBUG 3 /*INFO,ERR,WARN*/ +#define DEBUG 0 +#endif +#ifndef DEBUG2 +#define DEBUG2 0 +#endif +#define DEBUG_TRANSFER 0 +#define DEBUG_EP_STATE 0 +#define DEBUG_EVENT 0 + +#if (DEBUG > 3) +#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); +//#define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#define USB_DBG_HEX(A,B) debug_hex(A,B) +extern void debug_hex(uint8_t* buf, int size); +#define USB_DBG_ERRSTAT() report.print_errstat(); +#else +#define USB_DBG(x, ...) +#define USB_DBG_HEX(A,B) while(0) +#define USB_DBG_ERRSTAT() while(0) +#endif + +#if (DEBUG2 > 3) +#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); +#else +#define USB_DBG2(...) while(0); +#endif + +#if (DEBUG > 2) +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0); +//#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_INFO(x, ...) +#endif + +#if (DEBUG > 1) +#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_WARN(x, ...) +#endif + +#if (DEBUG > 0) +#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_ERR(x, ...) +#endif + +#if (DEBUG_TRANSFER) +#define USB_DBG_TRANSFER(x, ...) std::printf("[USB_TRANSFER: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_DBG_TRANSFER(x, ...) +#endif + +#if (DEBUG_EVENT) +#define USB_DBG_EVENT(x, ...) std::printf("[USB_EVENT: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define USB_DBG_EVENT(x, ...) +#endif + +#ifdef _USB_TEST +#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; +#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A)) +#else +#define USB_TEST_ASSERT(A) while(0) +#define USB_TEST_ASSERT_FALSE(A) while(0) +#endif + +#endif + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/mydebug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/mydebug.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,14 @@ +#pragma once +template<class SERIAL_T> +void debug_hex(SERIAL_T& pc, const uint8_t* buf, int size) +{ + for(int i = 0; i < size; i++) { + pc.printf("%02x ", buf[i]); + if (i%16 == 15) { + pc.puts("\n"); + } + } + pc.puts("\n"); +} + +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/mymap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/mymap.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,66 @@ +#pragma once + +template<class K,class T> +class mymap { + struct mypair { + K first; + T second; + }; +public: + mymap() { + m_size = 0; + } + T& operator[](const K& key) { + int it; + if (count(key) == 0) { + it = insert(key, 0); + } else { + it = find(key); + } + return m_buf[it].second; + } + bool empty() { return m_size == 0 ? true : false; } + int size() { return m_size; } + void clear() { m_size = 0; } + int count(K key) { + for(int i = 0; i < m_size; i++) { + if (m_buf[i].first == key) { + return 1; + } + } + return 0; + } + +private: + int find(K key) { + for(int i = 0; i < m_size; i++) { + if (m_buf[i].first == key) { + return i; + } + } + return -1; + } + int insert(K key, T value) { + int it = find(key); + if (it != -1) { + m_buf[it].second = value; + return it; + } + mypair* new_buf = new mypair[m_size+1]; + if (m_size > 0) { + for(int i = 0; i < m_size; i++) { + new_buf[i] = m_buf[i]; + } + delete[] m_buf; + } + m_buf = new_buf; + it = m_size++; + m_buf[it].first = key; + m_buf[it].second = value; + return it; + } + + int m_size; + mypair *m_buf; +}; +
diff -r 000000000000 -r 3dac1f1bc9e0 USBHost/myvector.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/myvector.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,35 @@ +#pragma once + +template<class T> +class myvector { +public: + myvector() { + m_size = 0; + m_buf = NULL; + } + ~myvector() { + if (m_buf) { + delete[] m_buf; + } + } + void push_back(T v) { + T* new_buf = new T[m_size+1]; + if (m_size > 0) { + for(int i = 0; i < m_size; i++) { + new_buf[i] = m_buf[i]; + } + delete[] m_buf; + } + m_buf = new_buf; + m_buf[m_size++] = v; + } + T& operator[](const int index) { + return m_buf[index]; + } + int size() { return m_size; } + +private: + int m_size; + T *m_buf; +}; +
diff -r 000000000000 -r 3dac1f1bc9e0 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/c0f6e94411f5 \ No newline at end of file
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,1065 @@ +/*===================================================================*/ +/* */ +/* pNesX.cpp : NES Emulator for PSX */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* 2016/ 1/20 Racoon Some optimization. */ +/* */ +/*===================================================================*/ + +/*------------------------------------------------------------------- + * File List : + * + * [NES Hardware] + * pNesX.cpp + * pNesX.h + * K6502_rw.h + * pNesX_Apu.cpp (Added) + * + * [Mapper function] + * pNesX_Mapper.cpp + * pNesX_Mapper.h + * + * [The function which depends on a system] + * pNesX_System_ooo.cpp (ooo is a system name. psx, win, Nucleo...) + * pNesX_System.h + * + * [CPU] + * K6502.cpp + * K6502.h + * + * [Others] + * pNesX_Types.h + * + --------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "mbed.h" +#include "pNesX.h" +#include "pNesX_System.h" +#include "pNesX_Mapper.h" +#include "K6502.h" + +/*-------------------------------------------------------------------*/ +/* NES resources */ +/*-------------------------------------------------------------------*/ + +/* RAM */ +BYTE RAM[ RAM_SIZE ]; + +/* SRAM */ +BYTE SRAM[ SRAM_SIZE ]; + +/* ROM */ +BYTE *ROM; + +/* ROM BANK ( 8Kb * 4 ) */ +BYTE *ROMBANK0; +BYTE *ROMBANK1; +BYTE *ROMBANK2; +BYTE *ROMBANK3; + +/*-------------------------------------------------------------------*/ +/* PPU resources */ +/*-------------------------------------------------------------------*/ + +/* PPU RAM */ +BYTE PPURAM[ PPURAM_SIZE ]; + +/* VROM */ +BYTE *VROM; + +/* PPU BANK ( 1Kb * 16 ) */ +BYTE *PPUBANK[ 16 ]; + +/* Sprite RAM */ +BYTE SPRRAM[ SPRRAM_SIZE ]; + +/* PPU Register */ +BYTE PPU_R0; +BYTE PPU_R1; +BYTE PPU_R2; +BYTE PPU_R3; +BYTE PPU_R7; + +/* Flag for PPU Address and Scroll Latch */ +BYTE PPU_Latch_Flag; + +/* Vertical scroll value */ +BYTE PPU_Scr_V; +BYTE PPU_Scr_V_Next; +BYTE PPU_Scr_V_Byte; +BYTE PPU_Scr_V_Byte_Next; +BYTE PPU_Scr_V_Bit; +BYTE PPU_Scr_V_Bit_Next; + +/* Horizontal scroll value */ +BYTE PPU_Scr_H; +BYTE PPU_Scr_H_Next; +BYTE PPU_Scr_H_Byte; +BYTE PPU_Scr_H_Byte_Next; +BYTE PPU_Scr_H_Bit; +BYTE PPU_Scr_H_Bit_Next; + +/* PPU Address */ +WORD PPU_Addr; + +/* The increase value of the PPU Address */ +WORD PPU_Increment; + +/* Current Scanline */ +WORD PPU_Scanline; + +/* Scanline Table */ +//BYTE PPU_ScanTable[ 263 ]; + +/* Name Table Bank */ +BYTE PPU_NameTableBank; + +/* BG Base Address */ +BYTE *PPU_BG_Base; + +/* Sprite Base Address */ +BYTE *PPU_SP_Base; + +/* Sprite Height */ +WORD PPU_SP_Height; + +/* Sprite #0 Scanline Hit Position */ +int SpriteHitPos; + +/*-------------------------------------------------------------------*/ +/* Display and Others resouces */ +/*-------------------------------------------------------------------*/ + +/* Frame Skip */ +WORD FrameSkip; +WORD FrameCnt; +bool FrameDraw; + +/* Display Line Buffer */ +WORD LineData[2][ NES_DISP_WIDTH ]; +WORD *pDrawData; +int LineDataIdx; + +/* Character Buffer */ +BYTE ChrBuf[ 256 * 2 * 8 * 8 ]; + +/* Update flag for ChrBuf */ +BYTE ChrBufUpdate; + +/* Palette Table */ +WORD PalTable[ 32 ]; + +/* Table for Mirroring */ +const BYTE PPU_MirrorTable[][ 4 ] = +{ + { NAME_TABLE0, NAME_TABLE0, NAME_TABLE1, NAME_TABLE1 }, + { NAME_TABLE0, NAME_TABLE1, NAME_TABLE0, NAME_TABLE1 }, + { NAME_TABLE1, NAME_TABLE1, NAME_TABLE1, NAME_TABLE1 }, + { NAME_TABLE0, NAME_TABLE0, NAME_TABLE0, NAME_TABLE0 } +}; + +/*-------------------------------------------------------------------*/ +/* APU and Pad resources */ +/*-------------------------------------------------------------------*/ + +/* APU Register */ +BYTE APU_Reg[ 0x18 ]; + +/* Pad data */ +DWORD PAD1_Latch; +DWORD PAD2_Latch; +DWORD PAD_System; +DWORD PAD1_Bit; +DWORD PAD2_Bit; + +/*-------------------------------------------------------------------*/ +/* Mapper Function */ +/*-------------------------------------------------------------------*/ + +/* Initialize Mapper */ +void (*MapperInit)(); +/* Write to Mapper */ +void (*MapperWrite)( WORD wAddr, BYTE byData ); +/* Callback at VSync */ +void (*MapperVSync)(); +/* Callback at HSync */ +void (*MapperHSync)(); + +/*-------------------------------------------------------------------*/ +/* ROM information */ +/*-------------------------------------------------------------------*/ + +/* .nes File Header */ +struct NesHeader_tag NesHeader; + +/* Mapper Number */ +BYTE MapperNo; + +/* Mirroring 0:Horizontal 1:Vertical */ +BYTE ROM_Mirroring; +/* It has SRAM */ +BYTE ROM_SRAM; +/* It has Trainer */ +BYTE ROM_Trainer; +/* Four screen VRAM */ +BYTE ROM_FourScr; + +/*===================================================================*/ +/* */ +/* pNesX_Init() : Initialize pNesX */ +/* */ +/*===================================================================*/ +void pNesX_Init() +{ +/* + * Initialize pNesX + * + * Remarks + * Initialize K6502 and Scanline Table. + */ + + // Initialize 6502 + K6502_Init(); +} + +/*===================================================================*/ +/* */ +/* pNesX_Fin() : Completion treatment */ +/* */ +/*===================================================================*/ +void pNesX_Fin() +{ +/* + * Completion treatment + * + * Remarks + * Release resources + */ + + // Release a memory for ROM + pNesX_ReleaseRom(); +} + +/*===================================================================*/ +/* */ +/* pNesX_Load() : Load a cassette */ +/* */ +/*===================================================================*/ +int pNesX_Load( const char *pszFileName ) +{ +/* + * Load a cassette + * + * Parameters + * const char *pszFileName (Read) + * File name of ROM image + * + * Return values + * 0 : It was finished normally. + * -1 : An error occurred. + * + * Remarks + * Read a ROM image in the memory. + * Reset pNesX. + */ + + // Release a memory for ROM + pNesX_ReleaseRom(); + + // Read a ROM image in the memory + if ( pNesX_ReadRom( pszFileName ) < 0 ) + return -1; + + // Reset pNesX + if ( pNesX_Reset() < 0 ) + return -1; + + // Successful + return 0; +} + +/*===================================================================*/ +/* */ +/* pNesX_Reset() : Reset pNesX */ +/* */ +/*===================================================================*/ +int pNesX_Reset() +{ +/* + * Reset pNesX + * + * Return values + * 0 : Normally + * -1 : Non support mapper + * + * Remarks + * Initialize Resources, PPU and Mapper. + * Reset CPU. + */ + + int nIdx; + + /*-------------------------------------------------------------------*/ + /* Get information on the cassette */ + /*-------------------------------------------------------------------*/ + + // Get Mapper Number + MapperNo = NesHeader.byInfo1 >> 4; + + // Check bit counts of Mapper No. + for ( nIdx = 4; nIdx < 8 && NesHeader.byReserve[ nIdx ] == 0; ++nIdx ) + ; + + if ( nIdx == 8 ) + { + // Mapper Number is 8bits + MapperNo |= ( NesHeader.byInfo2 & 0xf0 ); + } + + // Get information on the ROM + ROM_Mirroring = NesHeader.byInfo1 & 1; + ROM_SRAM = NesHeader.byInfo1 & 2; + ROM_Trainer = NesHeader.byInfo1 & 4; + ROM_FourScr = NesHeader.byInfo1 & 8; + + /*-------------------------------------------------------------------*/ + /* Initialize resources */ + /*-------------------------------------------------------------------*/ + + // Clear RAM + pNesX_MemorySet( RAM, 0, sizeof RAM ); + + // Reset frame skip and frame count + FrameSkip = 2; // 0:full 1:half 2:2/3 3:1/3 + FrameCnt = 0; + + + // Reset update flag of ChrBuf + ChrBufUpdate = 0xff; + + // Reset palette table + pNesX_MemorySet( PalTable, 0, sizeof PalTable ); + + // Reset APU register + pNesX_MemorySet( APU_Reg, 0, sizeof APU_Reg ); + + // Reset joypad + PAD1_Latch = PAD2_Latch = PAD_System = 0; + PAD1_Bit = PAD2_Bit = 0; + + /*-------------------------------------------------------------------*/ + /* Initialize PPU */ + /*-------------------------------------------------------------------*/ + + pNesX_SetupPPU(); + + /*-------------------------------------------------------------------*/ + /* Initialize Mapper */ + /*-------------------------------------------------------------------*/ + + // Get Mapper Table Index + for ( nIdx = 0; MapperTable[ nIdx ].nMapperNo != -1; ++nIdx ) + { + if ( MapperTable[ nIdx ].nMapperNo == MapperNo ) + break; + } + + if ( MapperTable[ nIdx ].nMapperNo == -1 ) + { + // Non support mapper + return -1; + } + + // Set up a mapper initialization function + MapperTable[ nIdx ].pMapperInit(); + + /*-------------------------------------------------------------------*/ + /* Reset CPU */ + /*-------------------------------------------------------------------*/ + + K6502_Reset(); + + // Successful + return 0; +} + +/*===================================================================*/ +/* */ +/* pNesX_SetupPPU() : Initialize PPU */ +/* */ +/*===================================================================*/ +void pNesX_SetupPPU() +{ +/* + * Initialize PPU + * + */ + int nPage; + + // Clear PPU and Sprite Memory + pNesX_MemorySet( PPURAM, 0, sizeof PPURAM ); + pNesX_MemorySet( SPRRAM, 0, sizeof SPRRAM ); + + // Reset PPU Register + PPU_R0 = PPU_R1 = PPU_R2 = PPU_R3 = PPU_R7 = 0; + + // Reset latch flag + PPU_Latch_Flag = 0; + + // Reset Scroll values + PPU_Scr_V = PPU_Scr_V_Next = PPU_Scr_V_Byte = PPU_Scr_V_Byte_Next = PPU_Scr_V_Bit = PPU_Scr_V_Bit_Next = 0; + PPU_Scr_H = PPU_Scr_H_Next = PPU_Scr_H_Byte = PPU_Scr_H_Byte_Next = PPU_Scr_H_Bit = PPU_Scr_H_Bit_Next = 0; + + // Reset PPU address + PPU_Addr = 0; + + // Reset scanline + PPU_Scanline = 0; + + // Reset hit position of sprite #0 + SpriteHitPos = 0; + + // Reset information on PPU_R0 + PPU_Increment = 1; + PPU_NameTableBank = NAME_TABLE0; + PPU_BG_Base = ChrBuf; + PPU_SP_Base = ChrBuf + 256 * 64; + PPU_SP_Height = 8; + + // Reset PPU banks + for ( nPage = 0; nPage < 16; ++nPage ) + PPUBANK[ nPage ] = &PPURAM[ nPage * 0x400 ]; + + /* Mirroring of Name Table */ + pNesX_Mirroring( ROM_Mirroring ); +} + +/*===================================================================*/ +/* */ +/* pNesX_Mirroring() : Set up a Mirroring of Name Table */ +/* */ +/*===================================================================*/ +void pNesX_Mirroring( int nType ) +{ +/* + * Set up a Mirroring of Name Table + * + * Parameters + * int nType (Read) + * Mirroring Type + * 0 : Horizontal + * 1 : Vertical + * 2 : One Screen 0x2000 + * 3 : One Screen 0x2400 + */ + + PPUBANK[ NAME_TABLE0 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 0 ] * 0x400 ]; + PPUBANK[ NAME_TABLE1 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 1 ] * 0x400 ]; + PPUBANK[ NAME_TABLE2 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 2 ] * 0x400 ]; + PPUBANK[ NAME_TABLE3 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 3 ] * 0x400 ]; +} + +/*===================================================================*/ +/* */ +/* pNesX_Main() : The main loop of pNesX */ +/* */ +/*===================================================================*/ +void pNesX_Main() +{ +/* + * The main loop of pNesX + * + */ + + // Initialize pNesX + pNesX_Init(); + + // Main loop + while ( 1 ) + { + /*-------------------------------------------------------------------*/ + /* To the menu screen */ + /*-------------------------------------------------------------------*/ + if ( pNesX_Menu() == -1 ) + { + break; // Quit + } + + /*-------------------------------------------------------------------*/ + /* Start a NES emulation */ + /*-------------------------------------------------------------------*/ + pNesX_Cycle(); + } + + // Completion treatment + pNesX_Fin(); +} + +/*===================================================================*/ +/* */ +/* pNesX_Cycle() : The loop of emulation */ +/* */ +/*===================================================================*/ +void pNesX_Cycle() +{ +/* + * The loop of emulation + * + */ + + // Emulation loop + for (;;) + { + // Execute instructions + K6502_Step( 40 ); + + // Set a flag if a scanning line is a hit in the sprite #0 + if ( ( SPRRAM[ SPR_Y ] + SpriteHitPos ) == PPU_Scanline && + PPU_Scanline >= SCAN_ON_SCREEN_START && PPU_Scanline < SCAN_BOTTOM_OFF_SCREEN_START ) + //PPU_ScanTable[ PPU_Scanline ] == SCAN_ON_SCREEN ) + { + // Set a sprite hit flag + PPU_R2 |= R2_HIT_SP; + + // NMI is required if there is necessity + if ( ( PPU_R0 & R0_NMI_SP ) && ( PPU_R1 & R1_SHOW_SP ) ) + NMI_REQ; + } + + // Execute instructions + K6502_Step( 75 ); + + // A mapper function in H-Sync + MapperHSync(); + + // A function in H-Sync + if ( pNesX_HSync() == -1 ) + return; // To the menu screen + } +} + +/*===================================================================*/ +/* */ +/* pNesX_HSync() : A function in H-Sync */ +/* */ +/*===================================================================*/ +int pNesX_HSync() +{ +/* + * A function in H-Sync + * + * Return values + * 0 : Normally + * -1 : Exit an emulation + */ + + /*-------------------------------------------------------------------*/ + /* Render a scanline */ + /*-------------------------------------------------------------------*/ + if ( FrameDraw && + PPU_Scanline >= SCAN_ON_SCREEN_START && PPU_Scanline < SCAN_BOTTOM_OFF_SCREEN_START ) + { + pNesX_DrawLine(); + pNesX_TransmitLinedata(); + } + + /*-------------------------------------------------------------------*/ + /* Set new scroll values */ + /*-------------------------------------------------------------------*/ + PPU_Scr_V = PPU_Scr_V_Next; + PPU_Scr_V_Byte = PPU_Scr_V_Byte_Next; + PPU_Scr_V_Bit = PPU_Scr_V_Bit_Next; + + PPU_Scr_H = PPU_Scr_H_Next; + PPU_Scr_H_Byte = PPU_Scr_H_Byte_Next; + PPU_Scr_H_Bit = PPU_Scr_H_Bit_Next; + + /*-------------------------------------------------------------------*/ + /* Next Scanline */ + /*-------------------------------------------------------------------*/ + PPU_Scanline = ( PPU_Scanline == SCAN_VBLANK_END ) ? 0 : PPU_Scanline + 1; + + /*-------------------------------------------------------------------*/ + /* Operation in the specific scanning line */ + /*-------------------------------------------------------------------*/ + switch ( PPU_Scanline ) + { + case SCAN_ON_SCREEN_START: + // Reset a PPU status + PPU_R2 = 0; + + // Set up a character data + if ( NesHeader.byVRomSize == 0 && FrameDraw ) + pNesX_SetupChr(); + + // Get position of sprite #0 + pNesX_GetSprHitY(); + break; + + case SCAN_VBLANK_START: + // Frame skip + FrameCnt = ++FrameCnt % 6; + switch (FrameSkip) + { + case 0: // full + FrameDraw = true; + break; + + case 1: // 1/2 + FrameDraw = FrameCnt & 1; + break; + + case 2: // 2/3 + FrameDraw = !(FrameCnt == 2 || FrameCnt == 5); + break; + + case 3: // 1/3 + FrameDraw = FrameCnt == 0 || FrameCnt == 3; + } + + pNesX_LoadFrame(); + + // Set a V-Blank flag + PPU_R2 = R2_IN_VBLANK; + + // Reset latch flag + PPU_Latch_Flag = 0; + + // A mapper function in V-Sync + MapperVSync(); + + // Get the condition of the joypad + pNesX_PadState( &PAD1_Latch, &PAD2_Latch, &PAD_System ); + + // NMI on V-Blank + if ( PPU_R0 & R0_NMI_VB ) + NMI_REQ; + + // Exit an emulation if a QUIT button is pushed + static DWORD quitWait; + if (PAD_PUSH( PAD_System, PAD_SYS_QUIT )) + { + quitWait++; + } + else + { + if (quitWait > 10) + { + quitWait = 0; + return -1; // Exit an emulation + } + quitWait = 0; + } + break; + + case SCAN_APU_CLK1: // 240Hz + case SCAN_APU_CLK3: // 240Hz + pNesX_ApuClk_240Hz(); + break; + + case SCAN_APU_CLK2: // 240Hz 120Hz + pNesX_ApuClk_240Hz(); + pNesX_ApuClk_120Hz(); + break; + + case SCAN_APU_CLK4: // 240Hz 120Hz 60Hz + pNesX_ApuClk_240Hz(); + pNesX_ApuClk_120Hz(); + pNesX_ApuClk_60Hz(); + break; + + } + + // Successful + return 0; +} + +/*===================================================================*/ +/* */ +/* pNesX_DrawLine() : Render a scanline */ +/* */ +/*===================================================================*/ + + +void pNesX_DrawLine() +{ +/* + * Render a scanline + * + */ + int nX; + int nY; + int nY4; + int nYBit; + WORD *pPalTbl; + BYTE *pAttrBase; + WORD *pPoint; + int nNameTable; + BYTE *pbyNameTable; + BYTE *pbyChrData; + BYTE *pSPRRAM; + int nAttr; + int nSprCnt; + int nIdx; + BYTE bySprCol; + bool bMask[ NES_DISP_WIDTH ]; + bool *pMask; + + // Pointer to the render position + pPoint = LineData[LineDataIdx]; + LineDataIdx = LineDataIdx == 0 ? 1 : 0; + pDrawData = pPoint; + + // Clear a scanline if screen is off + if ( !( PPU_R1 & R1_SHOW_SCR ) ) + { + pNesX_MemorySet( pPoint, 0, NES_DISP_WIDTH << 1 ); + return; + } + + nNameTable = PPU_NameTableBank; + + nY = PPU_Scr_V_Byte + ( PPU_Scanline >> 3 ); + + nYBit = PPU_Scr_V_Bit + ( PPU_Scanline & 7 ); + + if ( nYBit > 7 ) + { + ++nY; + nYBit &= 7; + } + nYBit <<= 3; + + if ( nY > 29 ) + { + // Next NameTable (An up-down direction) + nNameTable ^= NAME_TABLE_V_MASK; + nY -= 30; + } + + nX = PPU_Scr_H_Byte; + + nY4 = ( ( nY & 2 ) << 1 ); + + pMask = bMask; + + /*-------------------------------------------------------------------*/ + /* Rendering of the block of the left end */ + /*-------------------------------------------------------------------*/ + + pbyNameTable = PPUBANK[ nNameTable ] + nY * 32 + nX; + pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit; + pAttrBase = PPUBANK[ nNameTable ] + 0x3c0 + ( nY / 4 ) * 8; + pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ]; + + for ( nIdx = PPU_Scr_H_Bit; nIdx < 8; ++nIdx ) + { + *( pPoint++ ) = pPalTbl[ pbyChrData[ nIdx ] ]; + *pMask++ = pbyChrData[ nIdx ] == 0; + } + + ++nX; + ++pbyNameTable; + + /*-------------------------------------------------------------------*/ + /* Rendering of the left table */ + /*-------------------------------------------------------------------*/ + + for ( ; nX < 32; ++nX ) + { + pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit; + pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ]; + + *pPoint++ = pPalTbl[ pbyChrData[ 0 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 1 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 2 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 3 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 4 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 5 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 6 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 7 ] ]; + + *pMask++ = pbyChrData[ 0 ] == 0; + *pMask++ = pbyChrData[ 1 ] == 0; + *pMask++ = pbyChrData[ 2 ] == 0; + *pMask++ = pbyChrData[ 3 ] == 0; + *pMask++ = pbyChrData[ 4 ] == 0; + *pMask++ = pbyChrData[ 5 ] == 0; + *pMask++ = pbyChrData[ 6 ] == 0; + *pMask++ = pbyChrData[ 7 ] == 0; + + ++pbyNameTable; + } + + // Holizontal Mirror + nNameTable ^= NAME_TABLE_H_MASK; + + pbyNameTable = PPUBANK[ nNameTable ] + nY * 32; + pAttrBase = PPUBANK[ nNameTable ] + 0x3c0 + ( nY / 4 ) * 8; + + /*-------------------------------------------------------------------*/ + /* Rendering of the right table */ + /*-------------------------------------------------------------------*/ + + for ( nX = 0; nX < PPU_Scr_H_Byte; ++nX ) + { + pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit; + pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ]; + + *pPoint++ = pPalTbl[ pbyChrData[ 0 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 1 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 2 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 3 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 4 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 5 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 6 ] ]; + *pPoint++ = pPalTbl[ pbyChrData[ 7 ] ]; + + *pMask++ = pbyChrData[ 0 ] == 0; + *pMask++ = pbyChrData[ 1 ] == 0; + *pMask++ = pbyChrData[ 2 ] == 0; + *pMask++ = pbyChrData[ 3 ] == 0; + *pMask++ = pbyChrData[ 4 ] == 0; + *pMask++ = pbyChrData[ 5 ] == 0; + *pMask++ = pbyChrData[ 6 ] == 0; + *pMask++ = pbyChrData[ 7 ] == 0; + + ++pbyNameTable; + } + + /*-------------------------------------------------------------------*/ + /* Rendering of the block of the right end */ + /*-------------------------------------------------------------------*/ + + pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit; + pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ]; + for ( nIdx = 0; nIdx < PPU_Scr_H_Bit; ++nIdx ) + { + pPoint[ nIdx ] = pPalTbl[ pbyChrData[ nIdx ] ]; + *pMask++ = pbyChrData[ nIdx ] == 0; + } + + /*-------------------------------------------------------------------*/ + /* Render a sprite */ + /*-------------------------------------------------------------------*/ + + if ( PPU_R1 & R1_SHOW_SP ) + { + // Reset Scanline Sprite Count + PPU_R2 &= ~R2_MAX_SP; + + // Render a sprite to the sprite buffer + pPoint = pDrawData; + nSprCnt = 0; + for ( pSPRRAM = SPRRAM + ( 63 << 2 ); pSPRRAM >= SPRRAM && + nSprCnt < 8; pSPRRAM -= 4 ) + { + nY = pSPRRAM[ SPR_Y ] + 1; + if ( nY > PPU_Scanline || nY + PPU_SP_Height <= PPU_Scanline ) + continue; // Next sprite + + /*-------------------------------------------------------------------*/ + /* A sprite in scanning line */ + /*-------------------------------------------------------------------*/ + + // Holizontal Sprite Count +1 + ++nSprCnt; + + nAttr = pSPRRAM[ SPR_ATTR ]; + nYBit = PPU_Scanline - nY; + nYBit = ( nAttr & SPR_ATTR_V_FLIP ) ? ( PPU_SP_Height - nYBit - 1 ) << 3 : nYBit << 3; + + if ( PPU_R0 & R0_SP_SIZE ) + { + // Sprite size 8x16 + if ( pSPRRAM[ SPR_CHR ] & 1 ) + { + pbyChrData = ChrBuf + 256 * 64 + ( ( pSPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit; + } + else + { + pbyChrData = ChrBuf + ( ( pSPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit; + } + } + else + { + // Sprite size 8x8 + pbyChrData = PPU_SP_Base + ( pSPRRAM[ SPR_CHR ] << 6 ) + nYBit; + } + + bool bSprFront = !(nAttr & SPR_ATTR_PRI); + bySprCol = (( nAttr & SPR_ATTR_COLOR ) << 2) + 0x10; + nX = pSPRRAM[ SPR_X ]; + + if ( nAttr & SPR_ATTR_H_FLIP ) + { + // Horizontal flip + if ( pbyChrData[ 0 ] && nX < 249 && (bSprFront || bMask[nX + 7]) ) + pPoint[ nX + 7 ] = PalTable[ bySprCol | pbyChrData[ 0 ] ]; + if ( pbyChrData[ 1 ] && nX < 250 && (bSprFront || bMask[nX + 6]) ) + pPoint[ nX + 6 ] = PalTable[ bySprCol | pbyChrData[ 1 ] ]; + if ( pbyChrData[ 2 ] && nX < 251 && (bSprFront || bMask[nX + 5]) ) + pPoint[ nX + 5 ] = PalTable[ bySprCol | pbyChrData[ 2 ] ]; + if ( pbyChrData[ 3 ] && nX < 252 && (bSprFront || bMask[nX + 4]) ) + pPoint[ nX + 4 ] = PalTable[ bySprCol | pbyChrData[ 3 ] ]; + if ( pbyChrData[ 4 ] && nX < 253 && (bSprFront || bMask[nX + 3]) ) + pPoint[ nX + 3 ] = PalTable[ bySprCol | pbyChrData[ 4 ] ]; + if ( pbyChrData[ 5 ] && nX < 254 && (bSprFront || bMask[nX + 2]) ) + pPoint[ nX + 2 ] = PalTable[ bySprCol | pbyChrData[ 5 ] ]; + if ( pbyChrData[ 6 ] && nX < 255 && (bSprFront || bMask[nX + 1]) ) + pPoint[ nX + 1 ] = PalTable[ bySprCol | pbyChrData[ 6 ] ]; + if ( pbyChrData[ 7 ] && (bSprFront || bMask[nX]) ) + pPoint[ nX ] = PalTable[ bySprCol | pbyChrData[ 7 ] ]; + } + else + { + // Non flip + if ( pbyChrData[ 0 ] && (bSprFront || bMask[nX]) ) + pPoint[ nX ] = PalTable[ bySprCol | pbyChrData[ 0 ] ]; + if ( pbyChrData[ 1 ] && nX < 255 && (bSprFront || bMask[nX + 1]) ) + pPoint[ nX + 1 ] = PalTable[ bySprCol | pbyChrData[ 1 ] ]; + if ( pbyChrData[ 2 ] && nX < 254 && (bSprFront || bMask[nX + 2]) ) + pPoint[ nX + 2 ] = PalTable[ bySprCol | pbyChrData[ 2 ] ]; + if ( pbyChrData[ 3 ] && nX < 253 && (bSprFront || bMask[nX + 3]) ) + pPoint[ nX + 3 ] = PalTable[ bySprCol | pbyChrData[ 3 ] ]; + if ( pbyChrData[ 4 ] && nX < 252 && (bSprFront || bMask[nX + 4]) ) + pPoint[ nX + 4 ] = PalTable[ bySprCol | pbyChrData[ 4 ] ]; + if ( pbyChrData[ 5 ] && nX < 251 && (bSprFront || bMask[nX + 5]) ) + pPoint[ nX + 5 ] = PalTable[ bySprCol | pbyChrData[ 5 ] ]; + if ( pbyChrData[ 6 ] && nX < 250 && (bSprFront || bMask[nX + 6]) ) + pPoint[ nX + 6 ] = PalTable[ bySprCol | pbyChrData[ 6 ] ]; + if ( pbyChrData[ 7 ] && nX < 249 && (bSprFront || bMask[nX + 7]) ) + pPoint[ nX + 7 ] = PalTable[ bySprCol | pbyChrData[ 7 ] ]; + } + } + + if ( nSprCnt == 8 ) + PPU_R2 |= R2_MAX_SP; // Set a flag of maximum sprites on scanline + } +} + +/*===================================================================*/ +/* */ +/* pNesX_GetSprHitY() : Get a position of scanline hits sprite #0 */ +/* */ +/*===================================================================*/ +void pNesX_GetSprHitY() +{ +/* + * Get a position of scanline hits sprite #0 + * + */ + + int nYBit; + DWORD *pdwChrData; + int nOff; + + if ( SPRRAM[ SPR_ATTR ] & SPR_ATTR_V_FLIP ) + { + // Vertical flip + nYBit = ( PPU_SP_Height - 1 ) << 3; + nOff = -2; + } + else + { + // Non flip + nYBit = 0; + nOff = 2; + } + + if ( PPU_R0 & R0_SP_SIZE ) + { + // Sprite size 8x16 + if ( SPRRAM[ SPR_CHR ] & 1 ) + { + pdwChrData = (DWORD *)( ChrBuf + 256 * 64 + ( ( SPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit ); + } + else + { + pdwChrData = (DWORD * )( ChrBuf + ( ( SPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit ); + } + } + else + { + // Sprite size 8x8 + pdwChrData = (DWORD *)( PPU_SP_Base + ( SPRRAM[ SPR_CHR ] << 6 ) + nYBit ); + } + + for ( SpriteHitPos = 1; SpriteHitPos < PPU_SP_Height + 1; ++SpriteHitPos ) + { + if ( pdwChrData[ 0 ] | pdwChrData[ 1 ] ) + return; // Scanline hits sprite #0 + + pdwChrData += nOff; + } + + // Scanline didn't hit sprite #0 + SpriteHitPos = SCAN_VBLANK_END; +} + +/*===================================================================*/ +/* */ +/* pNesX_SetupChr() : Develop character data */ +/* */ +/*===================================================================*/ +void pNesX_SetupChr() +{ +/* + * Develop character data + * + */ + + BYTE *pbyBGData; + BYTE byData1; + BYTE byData2; + int nIdx; + int nY; + int nOff; + static BYTE *pbyPrevBank[ 8 ]; + int nBank; + + for ( nBank = 0; nBank < 8; ++nBank ) + { + if ( pbyPrevBank[ nBank ] == PPUBANK[ nBank ] && !( ( ChrBufUpdate >> nBank ) & 1 ) ) + continue; // Next bank + + /*-------------------------------------------------------------------*/ + /* An address is different from the last time */ + /* or */ + /* An update flag is being set */ + /*-------------------------------------------------------------------*/ + + for ( nIdx = 0; nIdx < 64; ++nIdx ) + { + nOff = ( nBank << 12 ) + ( nIdx << 6 ); + + for ( nY = 0; nY < 8; ++nY ) + { + pbyBGData = PPUBANK[ nBank ] + ( nIdx << 4 ) + nY; + + byData1 = ( ( pbyBGData[ 0 ] >> 1 ) & 0x55 ) | ( pbyBGData[ 8 ] & 0xAA ); + byData2 = ( pbyBGData[ 0 ] & 0x55 ) | ( ( pbyBGData[ 8 ] << 1 ) & 0xAA ); + + ChrBuf[ nOff++ ] = ( byData1 >> 6 ) & 3; + ChrBuf[ nOff++ ] = ( byData2 >> 6 ) & 3; + ChrBuf[ nOff++ ] = ( byData1 >> 4 ) & 3; + ChrBuf[ nOff++ ] = ( byData2 >> 4 ) & 3; + ChrBuf[ nOff++ ] = ( byData1 >> 2 ) & 3; + ChrBuf[ nOff++ ] = ( byData2 >> 2 ) & 3; + ChrBuf[ nOff++ ] = byData1 & 3; + ChrBuf[ nOff++ ] = byData2 & 3; + } + } + // Keep this address + pbyPrevBank[ nBank ] = PPUBANK[ nBank ]; + } + + // Reset update flag + ChrBufUpdate = 0; +} +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,285 @@ +/*===================================================================*/ +/* */ +/* pNesX.h : NES Emulator for PSX */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* */ +/*===================================================================*/ + +#ifndef PNESX_H_INCLUDED +#define PNESX_H_INCLUDED + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "pNesX_Types.h" + +/*-------------------------------------------------------------------*/ +/* NES resources */ +/*-------------------------------------------------------------------*/ + +#define RAM_SIZE 0x2000 +#define SRAM_SIZE 0x2000 +#define PPURAM_SIZE 0x4000 +#define SPRRAM_SIZE 256 + +/* RAM */ +extern BYTE RAM[]; + +/* SRAM */ +extern BYTE SRAM[]; + +/* ROM */ +extern BYTE *ROM; + +/* ROM BANK ( 8Kb * 4 ) */ +extern BYTE *ROMBANK0; +extern BYTE *ROMBANK1; +extern BYTE *ROMBANK2; +extern BYTE *ROMBANK3; + +/*-------------------------------------------------------------------*/ +/* PPU resources */ +/*-------------------------------------------------------------------*/ + +/* PPU RAM */ +extern BYTE PPURAM[]; + +/* VROM */ +extern BYTE *VROM; + +/* PPU BANK ( 1Kb * 16 ) */ +extern BYTE *PPUBANK[]; + +#define NAME_TABLE0 8 +#define NAME_TABLE1 9 +#define NAME_TABLE2 10 +#define NAME_TABLE3 11 + +#define NAME_TABLE_V_MASK 2 +#define NAME_TABLE_H_MASK 1 + +/* Sprite RAM */ +extern BYTE SPRRAM[]; + +#define SPR_Y 0 +#define SPR_CHR 1 +#define SPR_ATTR 2 +#define SPR_X 3 +#define SPR_ATTR_COLOR 0x3 +#define SPR_ATTR_V_FLIP 0x80 +#define SPR_ATTR_H_FLIP 0x40 +#define SPR_ATTR_PRI 0x20 + +/* PPU Register */ +extern BYTE PPU_R0; +extern BYTE PPU_R1; +extern BYTE PPU_R2; +extern BYTE PPU_R3; +extern BYTE PPU_R7; + +extern BYTE PPU_Scr_V; +extern BYTE PPU_Scr_V_Next; +extern BYTE PPU_Scr_V_Byte; +extern BYTE PPU_Scr_V_Byte_Next; +extern BYTE PPU_Scr_V_Bit; +extern BYTE PPU_Scr_V_Bit_Next; + +extern BYTE PPU_Scr_H; +extern BYTE PPU_Scr_H_Next; +extern BYTE PPU_Scr_H_Byte; +extern BYTE PPU_Scr_H_Byte_Next; +extern BYTE PPU_Scr_H_Bit; +extern BYTE PPU_Scr_H_Bit_Next; + +extern BYTE PPU_Latch_Flag; +extern WORD PPU_Addr; +extern WORD PPU_Increment; + +#define R0_NMI_VB 0x80 +#define R0_NMI_SP 0x40 +#define R0_SP_SIZE 0x20 +#define R0_BG_ADDR 0x10 +#define R0_SP_ADDR 0x08 +#define R0_INC_ADDR 0x04 +#define R0_NAME_ADDR 0x03 + +#define R1_BACKCOLOR 0xe0 +#define R1_SHOW_SP 0x10 +#define R1_SHOW_SCR 0x08 +#define R1_CLIP_SP 0x04 +#define R1_CLIP_BG 0x02 +#define R1_MONOCHROME 0x01 + +#define R2_IN_VBLANK 0x80 +#define R2_HIT_SP 0x40 +#define R2_MAX_SP 0x20 +#define R2_WRITE_FLAG 0x10 + +#define SCAN_TOP_OFF_SCREEN_START 0 +#define SCAN_ON_SCREEN_START 8 +#define SCAN_BOTTOM_OFF_SCREEN_START 232 +#define SCAN_POSTRENDER_START 240 +#define SCAN_VBLANK_START 245 +#define SCAN_VBLANK_END 261 + +#define SCAN_APU_CLK1 45 // 240Hz +#define SCAN_APU_CLK2 110 // 240Hz 120Hz +#define SCAN_APU_CLK3 176 // 240Hz +#define SCAN_APU_CLK4 241 // 240Hz 120Hz 60Hz + +/* Current Scanline */ +extern WORD PPU_Scanline; + +/* Scanline Table */ +extern BYTE PPU_ScanTable[]; + +/* Name Table Bank */ +extern BYTE PPU_NameTableBank; + +/* BG Base Address */ +extern BYTE *PPU_BG_Base; + +/* Sprite Base Address */ +extern BYTE *PPU_SP_Base; + +/* Sprite Height */ +extern WORD PPU_SP_Height; + +/* NES display size */ +#define NES_DISP_WIDTH 256 +#define NES_DISP_HEIGHT 224 + +/*-------------------------------------------------------------------*/ +/* Display and Others resouces */ +/*-------------------------------------------------------------------*/ + +/* Frame Skip */ +extern WORD FrameSkip; +extern WORD FrameCnt; + +//extern WORD DoubleFrame[ 2 ][ NES_DISP_WIDTH * NES_DISP_HEIGHT ]; +//extern WORD DoubleFrame[ 2 ][ NES_DISP_WIDTH ]; +extern WORD *WorkFrame; +extern WORD WorkFrameIdx; + +extern BYTE ChrBuf[]; + +extern BYTE ChrBufUpdate; + +extern WORD PalTable[]; + +/*-------------------------------------------------------------------*/ +/* APU and Pad resources */ +/*-------------------------------------------------------------------*/ + +extern BYTE APU_Reg[]; + +extern DWORD PAD1_Latch; +extern DWORD PAD2_Latch; +extern DWORD PAD_System; +extern DWORD PAD1_Bit; +extern DWORD PAD2_Bit; + +#define PAD_SYS_QUIT 1 +#define PAD_SYS_OK 2 +#define PAD_SYS_CANCEL 4 +#define PAD_SYS_UP 8 +#define PAD_SYS_DOWN 0x10 +#define PAD_SYS_LEFT 0x20 +#define PAD_SYS_RIGHT 0x40 + +#define PAD_PUSH(a,b) ( ( (a) & (b) ) != 0 ) + +/*-------------------------------------------------------------------*/ +/* Mapper Function */ +/*-------------------------------------------------------------------*/ + +/* Initialize Mapper */ +extern void (*MapperInit)(); +/* Write to Mapper */ +extern void (*MapperWrite)( WORD wAddr, BYTE byData ); +/* Callback at VSync */ +extern void (*MapperVSync)(); +/* Callback at HSync */ +extern void (*MapperHSync)(); + +/*-------------------------------------------------------------------*/ +/* ROM information */ +/*-------------------------------------------------------------------*/ + +/* .nes File Header */ +struct NesHeader_tag +{ + BYTE byID[ 4 ]; + BYTE byRomSize; + BYTE byVRomSize; + BYTE byInfo1; + BYTE byInfo2; + BYTE byReserve[ 8 ]; +}; + +/* .nes File Header */ +extern struct NesHeader_tag NesHeader; + +/* Mapper No. */ +extern BYTE MapperNo; + +/* Other */ +extern BYTE ROM_Mirroring; +extern BYTE ROM_SRAM; +extern BYTE ROM_Trainer; +extern BYTE ROM_FourScr; + +/*-------------------------------------------------------------------*/ +/* Function prototypes */ +/*-------------------------------------------------------------------*/ + +/* Initialize pNesX */ +void pNesX_Init(); + +/* Completion treatment */ +void pNesX_Fin(); + +/* Load a cassette */ +int pNesX_Load( const char *pszFileName ); + +/* Reset pNesX */ +int pNesX_Reset(); + +/* Initialize PPU */ +void pNesX_SetupPPU(); + +/* Set up a Mirroring of Name Table */ +void pNesX_Mirroring( int nType ); + +/* The main loop of pNesX */ +void pNesX_Main(); + +/* The loop of emulation */ +void pNesX_Cycle(); + +/* A function in H-Sync */ +int pNesX_HSync(); + +/* Render a scanline */ +void pNesX_DrawLine(); + +/* Get a position of scanline hits sprite #0 */ +void pNesX_GetSprHitY(); + +/* Develop character data */ +void pNesX_SetupChr(); + +/* Apu */ +void ApuInit(); +void ApuWrite(WORD wAddr, BYTE byData); +BYTE ApuRead(WORD wAddr); +void pNesX_ApuClk_240Hz(); +void pNesX_ApuClk_120Hz(); +void pNesX_ApuClk_60Hz(); + +#endif /* !PNESX_H_INCLUDED */ + +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_Apu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_Apu.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,674 @@ +/*===================================================================*/ +/* */ +/* pNesX_Apu.cpp : NES APU emulation (for Nucleo) */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#include "mbed.h" +#include "SDFileSystem.h" + +#include "pNesX.h" +#include "pNesX_System.h" + +//==================== +// DAC +//==================== +AnalogOut DAC_Out(PA_4); +WORD TrDac, P1Dac, P2Dac, NsDac, MixDac; +#define DACFreq 24000 +// Pulse clock(8 steps) = 1789773 / 2 / DACFreq * 1000 +#define PuClock 37287 +// Triangle clock(32 steps) = 1789773 / DACFreq * 1000 +#define TrClock 74574 + +//==================== +// DAC Timer +//==================== +#define TIMx TIM4 +#define TIMx_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE +#define TIMx_IRQn TIM4_IRQn +#define TIMx_IRQHandler TIM4_IRQHandler +TIM_HandleTypeDef TimHandle; + +//==================== +// Audio channel variables +//==================== + +const BYTE LengthTable[] = {10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, + 12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30}; + +// Minimum Volume +#define MV 4096 +const WORD Pulse_Table[4][8] = { 0,MV, 0, 0, 0, 0, 0, 0, + 0,MV,MV, 0, 0, 0, 0, 0, + 0,MV,MV,MV,MV, 0, 0, 0, + MV, 0, 0,MV,MV,MV,MV,MV}; +// Pulse1 +bool P1Enable; +int P1Timer; +int P1WaveLength; +int P1WavePeriod; +int P1Lapse; +int P1Duty; +int P1Vol; +int P1LengthCounter; +int P1EnvSeq; +int P1EnvCnt; +int P1Sweep; +int P1SwCnt; +int P1SwLevel; +bool P1SwReloadFlag; +bool P1SwOverflow; + +// Pulse2 +bool P2Enable; +int P2Timer; +int P2WaveLength; +int P2WavePeriod; +int P2Lapse; +int P2Duty; +int P2Vol; +int P2LengthCounter; +int P2EnvSeq; +int P2EnvCnt; +int P2Sweep; +int P2SwCnt; +int P2SwLevel; +bool P2SwReloadFlag; +bool P2SwOverflow; + +// Triangle +bool TrEnable; +int TrTimer; +const WORD Triangle_Table[] = {61440,57344,53248,49152,45056,40960,36864,32768,28672,24576,20480,16384,12288,8192,4096,0, + 0,4096,8192,12288,16384,20480,24576,28672,32768,36864,40960,45056,49152,53248,57344,61440}; +bool LinearCounterReloadFlag; +int LinearCounter; +int TrLengthCounter; +int TrWaveLength; +int TrWavePeriod; +int TrLapse; + +// Noise +bool NsEnable; +const WORD Noise_Freq[] = {0,0,0,0,0,0,12000,11186,8860,7046,4710,3523,2349,1762,880,440}; +int NsFreq; +int NsSum; +int NsVol; +int NsLengthCounter; +int NsEnvSeq; +int NsEnvCnt; + +// DMC +int DmOutLevel; + +/*-------------------------------------------------------------------*/ +/* DAC Timer callback */ +/*-------------------------------------------------------------------*/ +extern "C" { +void TIMx_IRQHandler(void) +{ + HAL_TIM_IRQHandler(&TimHandle); +} + +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) +{ + TIMx_CLK_ENABLE(); + + HAL_NVIC_SetPriority(TIMx_IRQn, 4, 0); + HAL_NVIC_EnableIRQ(TIMx_IRQn); +} + +static void Error_Handler(void) +{ + while(1); +} +} // extern "C" + +/*-------------------------------------------------------------------*/ +/* Randomize value (Noise channel) */ +/*-------------------------------------------------------------------*/ +WORD ShiftReg = 1; + +WORD Rand96() +{ + ShiftReg |= ((ShiftReg ^ (ShiftReg >> 6)) & 1) << 15; + ShiftReg >>= 1; + return (ShiftReg & 1) ? MV : 0; +} + +WORD Rand32k() +{ + ShiftReg |= ((ShiftReg ^ (ShiftReg >> 1)) & 1) << 15; + ShiftReg >>= 1; + return (ShiftReg & 1) ? MV : 0; +} + +/*-------------------------------------------------------------------*/ +/* DAC Timer Interrup */ +/*-------------------------------------------------------------------*/ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + // Pulse1 + if (P1Enable && P1LengthCounter > 0 && !P1SwOverflow && P1Timer > 8) + { + P1Lapse += PuClock; + P1Lapse %= P1WavePeriod; + P1Dac = Pulse_Table[P1Duty][P1Lapse / P1WaveLength] * P1Vol; + } + + // Pulse2 + if (P2Enable && P2LengthCounter > 0 && !P2SwOverflow && P2Timer > 8) + { + P2Lapse += PuClock; + P2Lapse %= P2WavePeriod; + P2Dac = Pulse_Table[P2Duty][P2Lapse / P2WaveLength] * P2Vol; + } + + // Triangle + if (TrEnable && LinearCounter > 0 && TrLengthCounter > 0) + { + TrLapse += TrClock; + TrLapse %= TrWavePeriod; + TrDac = Triangle_Table[TrLapse / TrWaveLength]; + TrDac -= (TrDac * DmOutLevel / 295); + } + + // Noise + if (NsEnable && NsLengthCounter > 0) + { + NsSum += NsFreq; + if (NsSum >= DACFreq) + { + NsSum %= DACFreq; + + NsDac = ((APU_Reg[0xe] & 0x80) ? Rand96() : Rand32k()) * NsVol; + NsDac -= (NsDac * DmOutLevel / 295); + } + } + + // Mixing + MixDac = (P1Dac + P2Dac + TrDac + NsDac) / 4; + + // Output to DAC + DAC_Out.write_u16(MixDac); +} + +/*-------------------------------------------------------------------*/ +/* Apu Initialize Function */ +/*-------------------------------------------------------------------*/ +void ApuInit() +{ + // Setup DAC Timer + TimHandle.Instance = TIMx; + TimHandle.Init.Prescaler = (uint32_t) ((SystemCoreClock / 2) / 240000) - 1; // 240000Hz + TimHandle.Init.Period = 10 - 1; // 240000/10=24000Hz + TimHandle.Init.ClockDivision = 0; + TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; + + if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK) + Error_Handler(); + + if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK) + Error_Handler(); +} + +/*-------------------------------------------------------------------*/ +/* Apu Mute */ +/*-------------------------------------------------------------------*/ +void ApuMute(bool mute) +{ + if (mute) + { + if(HAL_TIM_Base_Stop_IT(&TimHandle) != HAL_OK) + Error_Handler(); + } + else + { + if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK) + Error_Handler(); + } +} + +/*-------------------------------------------------------------------*/ +/* Apu Write Function */ +/*-------------------------------------------------------------------*/ +void ApuWrite( WORD wAddr, BYTE byData ) +{ + APU_Reg[ wAddr ] = byData; + + switch( wAddr ) + { + //==================== + // Pulse1 + //==================== + case 0: + P1Duty = (byData & 0xc0) >> 6; + + if (byData & 0x10) + { + // constant volume + P1Vol = byData & 0xf; + } + else + { + // envelope on + P1Vol = 15; + P1EnvCnt = (byData & 0xf) + 1; + } + break; + + case 1: + P1SwReloadFlag = true; + P1SwLevel = (byData & 7); + break; + + case 2: + case 3: + P1Timer = APU_Reg[3] & 7; + P1Timer = (P1Timer << 8) | APU_Reg[2]; + P1WaveLength = (P1Timer+1) * 1000; + P1WavePeriod = P1WaveLength * 8; + + if (wAddr == 3) + { + P1LengthCounter = LengthTable[(byData & 0xf8) >> 3]; + + // Reset sequencer + P1Lapse = 0; + P1EnvSeq = P1EnvCnt; + P1Sweep = 0; + P1SwCnt = 0; + P1SwOverflow = false; + } + break; + + //==================== + // Pulse2 + //==================== + case 4: + P2Duty = (byData & 0xc0) >> 6; + + if (byData & 0x10) + { + // constant volume + P2Vol = byData & 0xf; + } + else + { + // envelope on + P2Vol = 15; + P2EnvCnt = (byData & 0xf) + 1; + } + break; + + case 5: + P2SwReloadFlag = true; + P2SwLevel = (byData & 7); + break; + + case 6: + case 7: + P2Timer = APU_Reg[7] & 7; + P2Timer = (P2Timer << 8) | APU_Reg[6]; + P2WaveLength = (P2Timer+1) * 1000; + P2WavePeriod = P2WaveLength * 8; + if (wAddr == 7) + { + P2LengthCounter = LengthTable[(byData & 0xf8) >> 3]; + + // Reset sequencer + P2Lapse = 0; + P2EnvSeq = P2EnvCnt; + P2Sweep = 0; + P2SwCnt = 0; + P2SwOverflow = false; + } + break; + + //==================== + // Triangle + //==================== + case 0x8: + LinearCounterReloadFlag = true; + break; + + case 0xA: + case 0xB: + TrTimer = APU_Reg[0xB] & 7; + TrTimer = (TrTimer << 8) | APU_Reg[0xA]; + TrWaveLength = TrTimer * 1000; + TrWavePeriod = TrWaveLength * 32; + + if (wAddr == 0xB) + { + TrLengthCounter = LengthTable[(byData & 0xf8) >> 3]; + LinearCounterReloadFlag = true; + } + break; + + //==================== + // Noise + //==================== + case 0xC: + if (byData & 0x10) + { + // constant volume + NsVol = byData & 0xf; + } + else + { + // envelope on + NsVol = 15; + NsEnvCnt = (byData & 0xf) + 1; + } + break; + + case 0xF: + NsLengthCounter = LengthTable[(byData & 0xf8) >> 3]; + + // Reset sequencer + NsEnvSeq = NsEnvCnt; + break; + + case 0xE: + NsFreq = Noise_Freq[byData & 0xf]; + break; + + //==================== + // DMC(PCM) + //==================== + case 0x11: + DmOutLevel = byData & 0x7f; + break; + + //==================== + // Control + //==================== + case 0x15: + if (byData & 1) + { + P1Enable = true; + } + else + { + P1Enable = false; + P1LengthCounter = 0; + } + + if (byData & 2) + { + P2Enable = true; + } + else + { + P2Enable = false; + P2LengthCounter = 0; + } + + if (byData & 4) + { + TrEnable = true; + } + else + { + TrEnable = false; + TrLengthCounter = 0; + } + + if (byData & 8) + { + NsEnable = true; + } + else + { + NsEnable = false; + NsLengthCounter = 0; + } + break; + } // Switch( wAddr ) +} + +/*-------------------------------------------------------------------*/ +/* 240Hz Clock */ +/*-------------------------------------------------------------------*/ +void pNesX_ApuClk_240Hz() +{ + //==================== + // Pulse1 Envelope + //==================== + if (!(APU_Reg[0] & 0x10) && P1EnvSeq > 0) + { + P1EnvSeq--; + if (P1EnvSeq == 0) + { + if (P1Vol > 0) + { + --P1Vol; + P1EnvSeq = P1EnvCnt; + } + else + { + if (APU_Reg[0] & 0x20) + { + P1Vol = 15; + P1EnvSeq = P1EnvCnt; + } + } + } + } + + //==================== + // Pulse2 Envelope + //==================== + if (!(APU_Reg[4] & 0x10) && P2EnvSeq > 0) + { + P2EnvSeq--; + if (P2EnvSeq == 0) + { + if (P2Vol > 0) + { + --P2Vol; + P2EnvSeq = P2EnvCnt; + } + else + { + if (APU_Reg[4] & 0x20) + { + P2Vol = 15; + P2EnvSeq = P2EnvCnt; + } + } + } + } + + //==================== + // Triangle Linear Counter + //==================== + if (LinearCounterReloadFlag) + { + LinearCounter = APU_Reg[0x8] & 0x7f; + } + else if (LinearCounter > 0) + { + LinearCounter--; + } + + if (!(APU_Reg[0x8] & 0x80)) + { + LinearCounterReloadFlag = false; + } + + //==================== + // Noise Envelope + //==================== + if (!(APU_Reg[0xc] & 0x10) && NsEnvSeq > 0) + { + NsEnvSeq--; + if (NsEnvSeq == 0) + { + if (NsVol > 0) + { + --NsVol; + NsEnvSeq = NsEnvCnt; + } + else + { + if (APU_Reg[0xc] & 0x20) + { + NsVol = 15; + NsEnvSeq = NsEnvCnt; + } + } + } + } +} + +/*-------------------------------------------------------------------*/ +/* 120Hz Clock */ +/*-------------------------------------------------------------------*/ +void pNesX_ApuClk_120Hz() +{ + //==================== + // Pulse1 Sweep + //==================== + if (P1SwReloadFlag) + { + P1Sweep = ((APU_Reg[1] & 0x70) >> 4) + 1; + P1SwCnt = 0; + P1SwReloadFlag = false; + } + else if (APU_Reg[1] & 0x80 && !P1SwOverflow) + { + P1SwCnt++; + if (P1SwCnt == P1Sweep) + { + P1SwCnt = 0; + + int sweep = P1Timer >> P1SwLevel; + int value = P1Timer; + if (APU_Reg[1] & 8) + { + value = value - sweep - 1; + if (value < 8) + { + P1SwOverflow = true; + return; + } + } + else + { + value = value + sweep; + if (value > 0x7ff) + { + P1SwOverflow = true; + return; + } + } + P1Timer = value; + + APU_Reg[3] &= 7; + APU_Reg[3] |= value >> 8; + APU_Reg[2] = value & 0xff; + + P1WaveLength = (value + 1) * 1000; + P1WavePeriod = P1WaveLength * 8; + } + } + + //==================== + // Pulse1 Sweep + //==================== + if (P2SwReloadFlag) + { + P2Sweep = ((APU_Reg[5] & 0x70) >> 4) + 1; + P2SwCnt = 0; + P2SwReloadFlag = false; + } + else if (APU_Reg[5] & 0x80 && !P2SwOverflow) + { + P2SwCnt++; + if (P2SwCnt == P2Sweep) + { + P2SwCnt = 0; + + int sweep = P2Timer >> P2SwLevel; + int value = P2Timer; + if (APU_Reg[5] & 8) + { + value = value - sweep; + if (value < 8) + { + P2SwOverflow = true; + return; + } + } + else + { + value = value + sweep; + if (value > 0x7ff) + { + P2SwOverflow = true; + return; + } + } + + P2Timer = value; + + APU_Reg[7] &= 7; + APU_Reg[7] |= value >> 8; + APU_Reg[6] = value & 0xff; + + P2WaveLength = (value + 1) * 1000; + P2WavePeriod = P2WaveLength * 8; + + } + } +} + +/*-------------------------------------------------------------------*/ +/* 60Hz Clock */ +/*-------------------------------------------------------------------*/ +void pNesX_ApuClk_60Hz() +{ + // Pulse1 + if (!(APU_Reg[0] & 0x20) && P1LengthCounter > 0) + { + P1LengthCounter--; + } + + // Pulse2 + if (!(APU_Reg[4] & 0x20) && P2LengthCounter > 0) + { + P2LengthCounter--; + } + + // Triangle + if (!(APU_Reg[0x8] & 0x80) && TrLengthCounter > 0) + { + TrLengthCounter--; + } + + // Noise + if (!(APU_Reg[0xc] & 0x20) && NsLengthCounter > 0) + { + NsLengthCounter--; + } + +} + +/*-------------------------------------------------------------------*/ +/* Status */ +/*-------------------------------------------------------------------*/ +BYTE ApuRead( WORD wAddr ) +{ + if (wAddr == 0x15) + { + return (P1LengthCounter > 0) | (P2LengthCounter > 0) << 1 | (TrLengthCounter > 0) << 2 | (NsLengthCounter > 0) << 3; + } + + return APU_Reg[ wAddr ]; +} +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_Filer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_Filer.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,374 @@ +/*===================================================================*/ +/* */ +/* pNesX_Filer.cpp : ROM selection screen */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#include "mbed.h" +#include "SDFileSystem.h" +#include "tft.h" + +extern void pNesX_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem ); +extern const unsigned char pNesX_logo[]; +extern const unsigned char Racoon_logo[]; + +#define LOGO_BACKCOLOR 0x86fd + +#define FOLDER_FILE_MAX 100 +#define LIST_ROWS 20 +#define LIST_TOP 40 +#define LIST_LEFT 4 + +int DispTop; // Top of the list +int SelIdx; // Cursor index +int FileCount; // Number of files in the folder + +// file information +typedef struct tagLISTITEM{ + char filename[33]; + bool isDir; + long size; +} LISTITEM; + +// folder file list +LISTITEM *flist; + +char szRomFolder[256]; +char szPrevFolder[256]; +char szRomFilename[33]; +char szRomPath[256]; + +/*-------------------------------------------------------------------*/ +/* Get file extension */ +/*-------------------------------------------------------------------*/ +char *get_ext(char *filename) +{ + int i; + for (i = strlen(filename) - 1; i >= 0; --i) { + if (filename[i] == '.') { + return &filename[i + 1]; + } + } + return NULL; +} + +/*-------------------------------------------------------------------*/ +/* Get file path */ +/*-------------------------------------------------------------------*/ +char *get_filepath(char *path, char *filename) +{ + static char filepath[256]; + + if (strncmp(path, "/sd", 3) != 0) + { + filepath[0] = 0; + return filepath; + } + + int len = strlen(path); + if (len < 4) { + strcpy(filepath, filename); + } else { + sprintf(filepath, "%s/%s", &path[4], filename); + } + + return filepath; +} + +/*-------------------------------------------------------------------*/ +/* Get file list in the folder */ +/*-------------------------------------------------------------------*/ +int get_filelist(char *path) +{ + DIR *dir = opendir(path); + if ( dir == NULL ) { + return 0; + } + + dirent *entry; + FILINFO fi; + fi.lfname = NULL; + fi.lfsize = 0; + int i = 0; + + // not root + if (strcmp(path, "/sd") != 0) { + strcpy(flist[i].filename, ".."); + flist[i].isDir = true; + i++; + } + + // folder + while ((entry = readdir(dir)) != NULL && i < FOLDER_FILE_MAX) { + if (f_stat(get_filepath(path, entry->d_name), &fi) == FR_OK) { + int len = strlen(entry->d_name); + len = len > 32 ? 32 : len; + if (entry->d_name[0] == '.') continue; + + memcpy(flist[i].filename, entry->d_name, len); + flist[i].filename[len] = 0; + flist[i].isDir = fi.fattrib & AM_DIR; + flist[i].size = fi.fsize; + ++i; + } + } + + closedir(dir); + + return i; +} + + +/*-------------------------------------------------------------------*/ +/* Get file information string */ +/*-------------------------------------------------------------------*/ +char* filedata(int idx) +{ + static char disptext[41]; + + if (flist[idx].isDir) { + sprintf(disptext, "%-32s <DIR>", flist[idx].filename); + } else { + sprintf(disptext, "%-32s %6d", flist[idx].filename, flist[idx].size); + } + + return disptext; +} + +/*-------------------------------------------------------------------*/ +/* Draw file list */ +/*-------------------------------------------------------------------*/ +void draw_list() +{ + int i,y; + + for (y = 0, i = DispTop; y < LIST_ROWS && i < FileCount; ++y, ++i) { + tft_text( LIST_LEFT, LIST_TOP + y * 8, filedata(i), TFT_WHITE, TFT_BLACK ); + } + + if (y < LIST_ROWS) { + tft_boxfill( 0, LIST_TOP + y * 8, 319, LIST_TOP + LIST_ROWS * 8 - 1, TFT_BLACK); + } +} + +/*-------------------------------------------------------------------*/ +/* Draw cursor */ +/*-------------------------------------------------------------------*/ +void draw_cursor(bool clear = false) +{ + int y = SelIdx - DispTop; + if (clear) { + tft_box( LIST_LEFT - 1, LIST_TOP + y * 8 - 1, LIST_LEFT + 39 * 8, LIST_TOP + y * 8 + 7, TFT_BLACK); + tft_text( LIST_LEFT, LIST_TOP + y * 8, filedata(SelIdx), TFT_WHITE, TFT_BLACK ); + } else { + tft_box( LIST_LEFT - 1, LIST_TOP + y * 8 - 1, LIST_LEFT + 39 * 8, LIST_TOP + y * 8 + 7, TFT_YELLOW); + tft_text( LIST_LEFT, LIST_TOP + y * 8, filedata(SelIdx), TFT_BLACK, TFT_YELLOW ); + } +} + +/*-------------------------------------------------------------------*/ +/* Draw back ground */ +/*-------------------------------------------------------------------*/ +void draw_frame() +{ + tft_boxfill( 0, 0, 319, 31, LOGO_BACKCOLOR); + tft_boxfill(0, 32, 319, 223, TFT_BLACK); + tft_boxfill( 0, 224, 319, 239, LOGO_BACKCOLOR); + + draw_bmp_4bpp(pNesX_logo, 8, 6); + tft_text( 200, 225, "L2:Emu<->Menu", TFT_BLACK, LOGO_BACKCOLOR ); + tft_text( 200, 233, "R1+R2:Reset", TFT_BLACK, LOGO_BACKCOLOR ); + draw_bmp_4bpp(Racoon_logo, 0, 224); +} + +/*-------------------------------------------------------------------*/ +/* Dialog window */ +/*-------------------------------------------------------------------*/ +void dialog(char *msg) +{ + if (msg) + { + tft_boxfill(0, 100, 319, 139, TFT_NAVY); + int len = strlen(msg); + len = len > 38 ? 38 : len; + msg[len] = 0; + int x = (40 - len) * 4; + tft_text(x, 116, msg, TFT_WHITE, TFT_NAVY); + } + else + { + tft_boxfill(0, 100, 319, 139, TFT_BLACK); + } +} + +/*-------------------------------------------------------------------*/ +/* Rom selection */ +/*-------------------------------------------------------------------*/ +// return code: +// 0 : File selected +// 1 : Return to Emu +// 2 : Reset +// -1: Error +int pNesX_Filer() +{ + DWORD dwPad1, dwPad2, dwSystem; + DWORD prev_dwPad1 = 0; + + bool loadFolder; + int keyrepeat = 1; + + // Draw back ground + draw_frame(); + + // init + flist = (LISTITEM *)malloc(sizeof(LISTITEM) * FOLDER_FILE_MAX); + if (flist == NULL) { + return -1; + } + + loadFolder = true; + int ret; + + while(1) { + if (loadFolder) { + // Drawing of the files in the folder + FileCount = get_filelist(szRomFolder); + + if (FileCount > 0) { + if (strcmp(szRomFolder, szPrevFolder) != 0) + { + DispTop = 0; + SelIdx = 0; + strcpy( szPrevFolder, szRomFolder); + } + draw_list(); + draw_cursor(); + } + loadFolder = false; + } + + pNesX_PadState( &dwPad1, &dwPad2, &dwSystem ); + + if (dwPad1 != prev_dwPad1) { + keyrepeat = 0; + } + + if (keyrepeat == 0 || keyrepeat >= 10) { + // Down + if (dwPad1 & 0x20) { + if (SelIdx < FileCount - 1) { + // clear cursor + draw_cursor(true); + + if (SelIdx - DispTop == LIST_ROWS - 1) { + DispTop++; + draw_list(); + } + + // draw new cursor + SelIdx++; + draw_cursor(); + } + } + + // Up + if (dwPad1 & 0x10) { + if (SelIdx > 0) { + // clear cursor + draw_cursor(true); + + if (SelIdx - DispTop == 0) { + DispTop--; + draw_list(); + } + + // draw new cursor + SelIdx--; + draw_cursor(); + } + } + + // Select + if (dwPad1 & 0x01) { + // clear cursor + draw_cursor(true); + + if (flist[SelIdx].isDir) { + // folder + if (strcmp(flist[SelIdx].filename, "..") != 0) { + sprintf(szRomFolder, "%s/%s", szRomFolder, flist[SelIdx].filename); + } else { + // upper folder + char *upper = strrchr(szRomFolder, '/'); + if (upper) { + *upper = 0; + } + } + + loadFolder = true; + } else { + char *ext = get_ext(flist[SelIdx].filename); + if (ext != NULL && strcasecmp(ext, "nes") == 0) + { + strcpy(szRomFilename, flist[SelIdx].filename); + + + strcpy(szRomPath, get_filepath(szRomFolder, szRomFilename)); + + ret = 0; + break; + } + else + { + dialog("not a rom file!!"); + wait(1); + dialog(NULL); + draw_list(); + draw_cursor(); + } + } + } + + // Return to Emu + if (dwSystem & 0x01) { + if ( szRomFilename[0] != 0 ) { + do { + wait(0.08); + pNesX_PadState( &dwPad1, &dwPad2, &dwSystem ); + + } while (dwSystem & 0x01); + + ret = 1; + break; + } + } + + // Reset + if (dwSystem & 0x02) { + if ( szRomFilename[0] != 0 ) { + do { + wait(0.08); + pNesX_PadState( &dwPad1, &dwPad2, &dwSystem ); + } while (dwSystem & 0x02); + + ret = 2; + break; + } + } + } + + keyrepeat++; + + prev_dwPad1 = dwPad1; + + wait(0.08); + } + + // release memory + free(flist); + + return ret; +} +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_Mapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_Mapper.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,589 @@ +/*===================================================================*/ +/* */ +/* pNesX_Mapper.cpp : pNesX Mapper Function */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* */ +/*===================================================================*/ + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "pNesX.h" +#include "pNesX_System.h" +#include "pNesX_Mapper.h" +#include "K6502.h" + +/*-------------------------------------------------------------------*/ +/* Table of Mapper initialize function */ +/*-------------------------------------------------------------------*/ + +struct MapperTable_tag MapperTable[] = +{ + { 0, Map0_Init }, + { 1, Map1_Init }, + { 2, Map2_Init }, + { 3, Map3_Init }, + { 4, Map4_Init }, + { -1, NULL } +}; + +/*===================================================================*/ +/* */ +/* Mapper 0 */ +/* */ +/*===================================================================*/ + +/*-------------------------------------------------------------------*/ +/* Initialize Mapper 0 */ +/*-------------------------------------------------------------------*/ +void Map0_Init() +{ + /* Initialize Mapper */ + MapperInit = Map0_Init; + + /* Write to Mapper */ + MapperWrite = Map0_Write; + + /* Callback at VSync */ + MapperVSync = Map0_VSync; + + /* Callback at HSync */ + MapperHSync = Map0_HSync; + + /* Set ROM Banks */ + ROMBANK0 = ROMPAGE( 0 ); + ROMBANK1 = ROMPAGE( 1 ); + ROMBANK2 = ROMLASTPAGE( 1 ); + ROMBANK3 = ROMLASTPAGE( 0 ); + + /* Set PPU Banks */ + if ( NesHeader.byVRomSize > 0 ) + { + for ( int nPage = 0; nPage < 8; ++nPage ) + PPUBANK[ nPage ] = &VROM[ nPage * 0x400 ]; + + pNesX_SetupChr(); + } + + /* Set up wiring of the interrupt pin */ + K6502_Set_Int_Wiring( 1, 1 ); +} + +/*-------------------------------------------------------------------*/ +/* Mapper 0 Write Function */ +/*-------------------------------------------------------------------*/ +void Map0_Write( WORD wAddr, BYTE byData ) +{ +/* + * Dummy Write to Mapper + * + */ +} + +/*-------------------------------------------------------------------*/ +/* Mapper 0 V-Sync Function */ +/*-------------------------------------------------------------------*/ +void Map0_VSync() +{ +/* + * Dummy Callback at VSync + * + */ +} + +/*-------------------------------------------------------------------*/ +/* Mapper 0 H-Sync Function */ +/*-------------------------------------------------------------------*/ +void Map0_HSync() +{ +/* + * Dummy Callback at HSync + * + */ +} + +/*===================================================================*/ +/* */ +/* Mapper 1 */ +/* */ +/*===================================================================*/ + +BYTE Map1_Reg[ 4 ]; + +int Map1_Cnt; +BYTE Map1_Latch; + +/*-------------------------------------------------------------------*/ +/* Initialize Mapper 1 */ +/*-------------------------------------------------------------------*/ +void Map1_Init() +{ + int nPage; + + /* Initialize Mapper */ + MapperInit = Map1_Init; + + /* Write to Mapper */ + MapperWrite = Map1_Write; + + /* Callback at VSync */ + MapperVSync = Map0_VSync; + + /* Callback at HSync */ + MapperHSync = Map0_HSync; + + pNesX_MemorySet( Map1_Reg, 0, sizeof Map1_Reg ); + Map1_Cnt = Map1_Latch = 0; + + /* Set ROM Banks */ + ROMBANK0 = ROMPAGE( 0 ); + ROMBANK1 = ROMPAGE( 1 ); + ROMBANK2 = ROMLASTPAGE( 1 ); + ROMBANK3 = ROMLASTPAGE( 0 ); + + /* Set PPU VROM Banks */ + if ( NesHeader.byVRomSize > 0 ) + { + for ( nPage = 0; nPage < 8; ++nPage ) + PPUBANK[ nPage ] = &VROM[ nPage * 0x400 ]; + + pNesX_SetupChr(); + } + + /* Set up wiring of the interrupt pin */ + K6502_Set_Int_Wiring( 1, 1 ); +} + +/*-------------------------------------------------------------------*/ +/* Mapper 1 Write Function */ +/*-------------------------------------------------------------------*/ +void Map1_Write( WORD wAddr, BYTE byData ) +{ +/* + * MMC1 + */ + + int nReg; + int nROMPos; + int nBank; + int nVBank; + int nPage; + + nReg = ( wAddr >> 13 ) - 4; + + if ( byData & 0x80 ) + { + // Reset + Map1_Reg[ 0 ] |= 0xc; + Map1_Cnt = 0; + Map1_Latch = 0; + return; + } + else + { + // Bit Data Set + Map1_Latch |= ( ( byData & 1 ) << Map1_Cnt ); + ++Map1_Cnt; + } + + if ( Map1_Cnt < 5 ) + return; + + // 5Bits Latched + Map1_Reg[ nReg ] = ( nReg == 3 ) ? ( Map1_Latch & 0xf ) : Map1_Latch; + Map1_Cnt = 0; + Map1_Latch = 0; + + // Name Table Mirroring + pNesX_Mirroring( ( Map1_Reg[ 0 ] & 3 ) ^ 3 ); + + // Select Program ROM Bank + + // 256K ROM Position Selection + nROMPos = 0; + if ( NesHeader.byRomSize == 32 ) + { + /* 512K Program ROM */ + // 0 (First 256K) or 32 (Second 256K) + nROMPos = ( Map1_Reg[ 1 ] & 0x10 ) << 1; + } + else + if ( NesHeader.byRomSize == 64 ) + { + /* 1024K Program ROM */ + if ( Map1_Reg[ 0 ] & 0x10 ) + { + // Acknowledge 256K selection register 1 + nROMPos = ( ( Map1_Reg[ 1 ] & 0x10 ) << 1 ) | + ( ( Map1_Reg[ 2 ] & 0x10 ) << 2 ); + } + else + { + // Ignore 256K selection register 1 + // 0 (First 256K) or 64 (Third 256K) + nROMPos = ( Map1_Reg[ 1 ] & 0x10 ) << 2; + } + } + + // Set Program ROM Bank + if ( !( Map1_Reg[ 0 ] & 8 ) ) + { + // 32K ROM Bank + /* Set ROM Banks */ + nBank = ( ( Map1_Reg[ 3 ] << 2 ) + nROMPos ) % ( NesHeader.byRomSize << 1 ); + + ROMBANK0 = ROMPAGE( nBank ); + ROMBANK1 = ROMPAGE( nBank + 1 ); + ROMBANK2 = ROMPAGE( nBank + 2 ); + ROMBANK3 = ROMPAGE( nBank + 3 ); + } + else + if ( Map1_Reg[ 0 ] & 4 ) + { + // 16K ROM Bank at 0x8000 + nBank = ( ( Map1_Reg[ 3 ] << 1 ) + nROMPos ) % ( NesHeader.byRomSize << 1 ); + ROMBANK0 = ROMPAGE( nBank ); + ROMBANK1 = ROMPAGE( nBank + 1 ); + ROMBANK2 = ROMLASTPAGE( 1 ); + ROMBANK3 = ROMLASTPAGE( 0 ); + } + else + { + // 16K ROM Bank at 0xc000 + nBank = ( ( Map1_Reg[ 3 ] << 1 ) + nROMPos ) % ( NesHeader.byRomSize << 1 ); + ROMBANK0 = ROMPAGE( 0 ); + ROMBANK1 = ROMPAGE( 1 ); + ROMBANK2 = ROMPAGE( nBank ); + ROMBANK3 = ROMPAGE( nBank + 1 ); + } + + // Select PPU VROM Bank + if ( NesHeader.byVRomSize > 0 ) + { + if ( Map1_Reg[ 0 ] & 0x10 ) + { + // 4K VROM Switching + nVBank = Map1_Reg[ 1 ] % ( NesHeader.byVRomSize << 1 ); + for ( nPage = 0; nPage < 4; ++nPage ) + PPUBANK[ nPage ] = &VROM[ nVBank * 0x1000 + nPage * 0x400 ]; + + nVBank = Map1_Reg[ 2 ] % ( NesHeader.byVRomSize << 1 ); + for ( nPage = 0; nPage < 4; ++nPage ) + PPUBANK[ nPage + 4 ] = &VROM[ nVBank * 0x1000 + nPage * 0x400 ]; + } + else + { + // 8K VROM Switching + nVBank = ( Map1_Reg[ 1 ] & 0xe ) % ( NesHeader.byVRomSize << 1 ); + for ( nPage = 0; nPage < 8; ++nPage ) + PPUBANK[ nPage ] = &VROM[ nVBank * 0x1000 + nPage * 0x400 ]; + } + + pNesX_SetupChr(); + } +} + +/*===================================================================*/ +/* */ +/* Mapper 2 (UNROM) */ +/* */ +/*===================================================================*/ + +/*-------------------------------------------------------------------*/ +/* Initialize Mapper 2 */ +/*-------------------------------------------------------------------*/ +void Map2_Init() +{ + /* Initialize Mapper */ + MapperInit = Map2_Init; + + /* Write to Mapper */ + MapperWrite = Map2_Write; + + /* Callback at VSync */ + MapperVSync = Map0_VSync; + + /* Callback at HSync */ + MapperHSync = Map0_HSync; + + /* Set ROM Banks */ + ROMBANK0 = ROMPAGE( 0 ); + ROMBANK1 = ROMPAGE( 1 ); + ROMBANK2 = ROMLASTPAGE( 1 ); + ROMBANK3 = ROMLASTPAGE( 0 ); + + /* Set up wiring of the interrupt pin */ + K6502_Set_Int_Wiring( 1, 1 ); +} + +/*-------------------------------------------------------------------*/ +/* Mapper 2 Write Function */ +/*-------------------------------------------------------------------*/ +void Map2_Write( WORD wAddr, BYTE byData ) +{ + /* Set ROM Banks */ + byData %= NesHeader.byRomSize; + byData <<= 1; + + ROMBANK0 = ROMPAGE( byData ); + ROMBANK1 = ROMPAGE( byData + 1 ); +} + + +/*===================================================================*/ +/* */ +/* Mapper 3 (VROM Switch) */ +/* */ +/*===================================================================*/ + +/*-------------------------------------------------------------------*/ +/* Initialize Mapper 3 */ +/*-------------------------------------------------------------------*/ +void Map3_Init() +{ + int nPage; + + /* Initialize Mapper */ + MapperInit = Map3_Init; + + /* Write to Mapper */ + MapperWrite = Map3_Write; + + /* Callback at VSync */ + MapperVSync = Map0_VSync; + + /* Callback at HSync */ + MapperHSync = Map0_HSync; + + /* Set ROM Banks */ + ROMBANK0 = ROMPAGE( 0 ); + ROMBANK1 = ROMPAGE( 1 ); + ROMBANK2 = ROMLASTPAGE( 1 ); + ROMBANK3 = ROMLASTPAGE( 0 ); + + /* Set PPU Banks */ + if ( NesHeader.byVRomSize > 0 ) + { + for ( nPage = 0; nPage < 8; ++nPage ) + PPUBANK[ nPage ] = &VROM[ nPage * 0x400 ]; + pNesX_SetupChr(); + } + + /* Set up wiring of the interrupt pin */ + /* "DragonQuest" doesn't run if IRQ isn't made to occur in CLI */ + K6502_Set_Int_Wiring( 1, 0 ); +} + +/*-------------------------------------------------------------------*/ +/* Mapper 3 Write Function */ +/*-------------------------------------------------------------------*/ +void Map3_Write( WORD wAddr, BYTE byData ) +{ + int nPage; + + /* Set PPU Banks */ + byData %= NesHeader.byVRomSize; + for ( nPage = 0; nPage < 8; ++nPage ) + PPUBANK[ nPage ] = &VROM[ byData * 0x2000 + nPage * 0x400 ]; + + pNesX_SetupChr(); +} + +/*===================================================================*/ +/* */ +/* Mapper 4 (MMC3) */ +/* */ +/*===================================================================*/ + +BYTE Map4_VROM_Base; +BYTE Map4_ROM_Base; +BYTE Map4_Cmd; +BYTE Map4_Banks_Reg[ 8 ]; +BYTE Map4_IRQ_Cnt; +BYTE Map4_IRQ_Set; +BYTE Map4_IRQ_Enable; + +/*-------------------------------------------------------------------*/ +/* Initialize Mapper 4 */ +/*-------------------------------------------------------------------*/ +void Map4_Init() +{ + /* Initialize Mapper */ + MapperInit = Map4_Init; + + /* Write to Mapper */ + MapperWrite = Map4_Write; + + /* Callback at VSync */ + MapperVSync = Map4_VSync; + + /* Callback at HSync */ + MapperHSync = Map4_HSync; + + Map4_VROM_Base = Map4_ROM_Base = Map4_Cmd = Map4_IRQ_Cnt = Map4_IRQ_Set = Map4_IRQ_Enable = 0; + + Map4_Banks_Reg[ 0 ] = 0; + Map4_Banks_Reg[ 1 ] = 2; + Map4_Banks_Reg[ 2 ] = 4; + Map4_Banks_Reg[ 3 ] = 5; + Map4_Banks_Reg[ 4 ] = 6; + Map4_Banks_Reg[ 5 ] = 7; + Map4_Banks_Reg[ 6 ] = 0; + Map4_Banks_Reg[ 7 ] = 1; + + Map4_Write( 0x8000, 0 ); + Map4_Write( 0x8001, 0 ); + + /* Set up wiring of the interrupt pin */ + K6502_Set_Int_Wiring( 1, 1 ); +} + +/*-------------------------------------------------------------------*/ +/* Mapper 4 Write Function */ +/*-------------------------------------------------------------------*/ +void Map4_Write( WORD wAddr, BYTE byData ) +{ + WORD wMapAddr; + + wMapAddr = wAddr & 0xe001; + + switch ( wMapAddr ) + { + case 0xa000: + // Name Table Mirroring + pNesX_Mirroring( ~byData & 1 ); + break; + + case 0xa001: + break; + + case 0xc000: + Map4_IRQ_Cnt = byData; + break; + + case 0xc001: + Map4_IRQ_Set = byData; + break; + + case 0xe000: + Map4_IRQ_Cnt = Map4_IRQ_Set; + Map4_IRQ_Enable = 0; + break; + + case 0xe001: + if ( Map4_IRQ_Cnt > 0 ) + Map4_IRQ_Enable = 1; + break; + + default: + if ( wMapAddr == 0x8000 ) + { + Map4_VROM_Base = byData >> 7; + Map4_ROM_Base = ( byData >> 6 ) & 1; + Map4_Cmd = byData & 7; + return; + } + else + { + if ( Map4_Cmd >= 6 ) + byData %= ( NesHeader.byRomSize << 1 ); + else + if ( NesHeader.byVRomSize > 0 ) + { + if ( Map4_Cmd < 2 ) + byData = ( byData & 0xfe ) % ( NesHeader.byVRomSize << 3 ); + else + if ( Map4_Cmd < 6 ) + byData %= ( NesHeader.byVRomSize << 3 ); + } + + Map4_Banks_Reg[ Map4_Cmd ] = byData; + } + + /* Set VROM Banks */ + if ( NesHeader.byVRomSize > 0 ) + { + if ( Map4_VROM_Base ) + { + PPUBANK[ 0 ] = VROMPAGE( Map4_Banks_Reg[ 2 ] ); + PPUBANK[ 1 ] = VROMPAGE( Map4_Banks_Reg[ 3 ] ); + PPUBANK[ 2 ] = VROMPAGE( Map4_Banks_Reg[ 4 ] ); + PPUBANK[ 3 ] = VROMPAGE( Map4_Banks_Reg[ 5 ] ); + PPUBANK[ 4 ] = VROMPAGE( Map4_Banks_Reg[ 0 ] ); + PPUBANK[ 5 ] = VROMPAGE( Map4_Banks_Reg[ 0 ] + 1 ); + PPUBANK[ 6 ] = VROMPAGE( Map4_Banks_Reg[ 1 ] ); + PPUBANK[ 7 ] = VROMPAGE( Map4_Banks_Reg[ 1 ] + 1 ); + } + else + { + PPUBANK[ 0 ] = VROMPAGE( Map4_Banks_Reg[ 0 ] ); + PPUBANK[ 1 ] = VROMPAGE( Map4_Banks_Reg[ 0 ] + 1 ); + PPUBANK[ 2 ] = VROMPAGE( Map4_Banks_Reg[ 1 ] ); + PPUBANK[ 3 ] = VROMPAGE( Map4_Banks_Reg[ 1 ] + 1 ); + PPUBANK[ 4 ] = VROMPAGE( Map4_Banks_Reg[ 2 ] ); + PPUBANK[ 5 ] = VROMPAGE( Map4_Banks_Reg[ 3 ] ); + PPUBANK[ 6 ] = VROMPAGE( Map4_Banks_Reg[ 4 ] ); + PPUBANK[ 7 ] = VROMPAGE( Map4_Banks_Reg[ 5 ] ); + } + + pNesX_SetupChr(); + } + + if ( Map4_ROM_Base ) + { + ROMBANK0 = ROMLASTPAGE( 1 ); + ROMBANK1 = ROMPAGE( Map4_Banks_Reg[ 7 ] ); + ROMBANK2 = ROMPAGE( Map4_Banks_Reg[ 6 ] ); + ROMBANK3 = ROMLASTPAGE( 0 ); + } + else + { + ROMBANK0 = ROMPAGE( Map4_Banks_Reg[ 6 ] ); + ROMBANK1 = ROMPAGE( Map4_Banks_Reg[ 7 ] ); + ROMBANK2 = ROMLASTPAGE( 1 ); + ROMBANK3 = ROMLASTPAGE( 0 ); + } + } +} + +/*-------------------------------------------------------------------*/ +/* Mapper 4 V-Sync Function */ +/*-------------------------------------------------------------------*/ +void Map4_VSync() +{ +/* + * Callback at VSync + * + */ + Map4_IRQ_Cnt = Map4_IRQ_Set; +} + +/*-------------------------------------------------------------------*/ +/* Mapper 4 H-Sync Function */ +/*-------------------------------------------------------------------*/ +void Map4_HSync() +{ +/* + * Callback at HSync + * + */ + + if ( Map4_IRQ_Enable && + PPU_Scanline >= SCAN_ON_SCREEN_START && PPU_Scanline < SCAN_BOTTOM_OFF_SCREEN_START && + //PPU_ScanTable[ PPU_Scanline ] == SCAN_ON_SCREEN && + ( PPU_R1 & ( R1_SHOW_SCR | R1_SHOW_SP ) ) == ( R1_SHOW_SCR | R1_SHOW_SP ) && + Map4_IRQ_Cnt > 0 ) + { + --Map4_IRQ_Cnt; + if ( Map4_IRQ_Cnt == 0 ) + { + Map4_IRQ_Cnt = Map4_IRQ_Set; + IRQ_REQ; + } + } +} + + +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_Mapper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_Mapper.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,67 @@ +/*===================================================================*/ +/* */ +/* pNesX_Mapper.h : pNesX Mapper Function */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* */ +/*===================================================================*/ + +#ifndef PNESX_MAPPER_H_INCLUDED +#define PNESX_MAPPER_H_INCLUDED + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "pNesX_Types.h" + +/*-------------------------------------------------------------------*/ +/* Macros */ +/*-------------------------------------------------------------------*/ + +/* The address of 8Kbytes unit of the ROM */ +#define ROMPAGE(a) &ROM[ (a) * 0x2000 ] +/* From behind the ROM, the address of 8kbytes unit */ +#define ROMLASTPAGE(a) &ROM[ NesHeader.byRomSize * 0x4000 - ( (a) + 1 ) * 0x2000 ] + +/* The address of 1Kbytes unit of the VROM */ +#define VROMPAGE(a) &VROM[ (a) * 0x400 ] + +/*-------------------------------------------------------------------*/ +/* Table of Mapper initialize function */ +/*-------------------------------------------------------------------*/ + +struct MapperTable_tag +{ + int nMapperNo; + void (*pMapperInit)(); +}; + +extern struct MapperTable_tag MapperTable[]; + +/*-------------------------------------------------------------------*/ +/* Function prototypes */ +/*-------------------------------------------------------------------*/ + +void Map0_Init(); +void Map0_Write( WORD wAddr, BYTE byData ); +void Map0_VSync(); +void Map0_HSync(); + +void Map1_Init(); +void Map1_Write( WORD wAddr, BYTE byData ); + +void Map2_Init(); +void Map2_Write( WORD wAddr, BYTE byData ); + +void Map3_Init(); +void Map3_Write( WORD wAddr, BYTE byData ); + +void Map4_Init(); +void Map4_Write( WORD wAddr, BYTE byData ); +void Map4_VSync(); +void Map4_HSync(); + +#endif /* !PNESX_MAPPER_H_INCLUDED */ + +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_System.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_System.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,54 @@ +/*===================================================================*/ +/* */ +/* pNesX_System.h : The function which depends on a system */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* */ +/*===================================================================*/ + +#ifndef PNESX_SYSTEM_H_INCLUDED +#define PNESX_SYSTEM_H_INCLUDED + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "pNesX_Types.h" + +/*-------------------------------------------------------------------*/ +/* Palette data */ +/*-------------------------------------------------------------------*/ +extern const WORD NesPalette[]; + +/*-------------------------------------------------------------------*/ +/* Function prototypes */ +/*-------------------------------------------------------------------*/ + +/* Menu screen */ +int pNesX_Menu(); + +/* Read ROM image file */ +int pNesX_ReadRom( const char *pszFileName ); + +/* Release a memory for ROM */ +void pNesX_ReleaseRom(); + +/* Transfer the contents of work frame on the screen */ +void pNesX_LoadFrame(); +void pNesX_TransmitLinedata(); + +/* Get a joypad state */ +void pNesX_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem ); + +/* memcpy */ +void *pNesX_MemoryCopy( void *dest, const void *src, int count ); + +/* memset */ +void *pNesX_MemorySet( void *dest, int c, int count ); + +/* Print debug message */ +void pNesX_DebugPrint( char *pszMsg ); + +#endif /* !PNESX_SYSTEM_H_INCLUDED */ + +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_System_Nucleo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_System_Nucleo.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,483 @@ +/*===================================================================*/ +/* */ +/* pNesX_System_Nucleo.cpp : The function which depends on a system */ +/* (for Nucleo F446RE) */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +/*-------------------------------------------------------------------*/ +/* Include files */ +/*-------------------------------------------------------------------*/ + +#include "mbed.h" +#include "SDFileSystem.h" +#include "tft.h" + +//#define PS_GAMEPAD + +#if !defined(PS_GAMEPAD) +#include "USBHostGamepad.h" +USBHostGamepad *pad; +#else +#include "pspad.h" +#endif + +#include "pNesX.h" +#include "pNesX_System.h" + +extern int pNesX_Filer(); +extern void ApuMute(bool mute); + +SDFileSystem *sd; //(PB_15, PB_14, PB_13, PA_9, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000); + +DigitalIn userbutton(USER_BUTTON); + +extern WORD LineData[][256]; +extern WORD *pDrawData; + +//#define SHOW_FPS + +#if defined(SHOW_FPS) +Timer timer; +int fps = 0; +int dmawait; +#endif + +/*-------------------------------------------------------------------*/ +/* ROM image file information */ +/*-------------------------------------------------------------------*/ + +extern char szRomFolder[]; +extern char szRomFilename[]; +extern char szRomPath[]; + +char szRomName[ 256 ]; +char szSaveName[ 256 ]; +int nSRAM_SaveFlag; + +// Palette data +const WORD NesPalette[ 64 ] = +{ + 0xef7b,0x1f00,0x1700,0x5741,0x1090,0x04a8,0x80a8,0xa088,0x8051,0xc003,0x4003,0xc002,0x0b02,0x0000,0x0000,0x0000, + 0xf7bd,0xdf03,0xdf02,0x3f6a,0x19d8,0x0be0,0xc0f9,0xe2e2,0xe0ab,0xc005,0x4005,0x4805,0x5104,0x0000,0x0000,0x0000, + 0xdfff,0xff3d,0x5f6c,0xdf9b,0xdffb,0xd3fa,0xcbfb,0x08fd,0xc0fd,0xc3bf,0xca5e,0xd35f,0x5b07,0xcf7b,0x0000,0x0000, + 0xffff,0x3fa7,0xdfbd,0xdfdd,0xdffd,0x38fd,0x96f6,0x15ff,0xcffe,0xcfdf,0xd7bf,0xdbbf,0xff07,0xdffe,0x0000,0x0000 +}; + +/*-------------------------------------------------------------------*/ +/* Function prototypes */ +/*-------------------------------------------------------------------*/ + +int LoadSRAM(); +int SaveSRAM(); + +/*===================================================================*/ +/* */ +/* LoadSRAM() : Load a SRAM */ +/* */ +/*===================================================================*/ +int LoadSRAM() +{ +/* + * Load a SRAM + * + * Return values + * 0 : Normally + * -1 : SRAM data couldn't be read + */ + + return 0; +} + +/*===================================================================*/ +/* */ +/* SaveSRAM() : Save a SRAM */ +/* */ +/*===================================================================*/ +int SaveSRAM() +{ +/* + * Save a SRAM + * + * Return values + * 0 : Normally + * -1 : SRAM data couldn't be written + */ + + + // Successful + return 0; +} + +/*===================================================================*/ +/* */ +/* pNesX_Menu() : Menu screen */ +/* */ +/*===================================================================*/ +int pNesX_Menu() +{ +/* + * Menu screen + * + * Return values + * 0 : Normally + * -1 : Exit pNesX + */ + +#if defined(SHOW_FPS) + timer.stop(); +#endif + + ApuMute(true); + + switch (pNesX_Filer()) + { + case 0: // Selected a file + if ( pNesX_Load( szRomPath ) == 0 ) + { + // Set a ROM image name + strcpy( szRomName, szRomFilename ); + + // Load SRAM + LoadSRAM(); + } + break; + + case 1: // Return to Emu + break; + + case 2: // Reset + if ( szRomName[ 0 ] != 0 ) + { + // Reset pNesX + pNesX_Reset(); + } + + break; + + case -1: // Error + printf("Filer Error\r\n"); + while(1); + } + + tft_clear(TFT_BLACK); + tft_set_window(32, 8, NES_DISP_WIDTH + 32 - 1, NES_DISP_HEIGHT + 8 - 1); + + ApuMute(false); + +#if defined(SHOW_FPS) + timer.start(); +#endif + + return 0; +} + +/*===================================================================*/ +/* */ +/* pNesX_ReadRom() : Read ROM image file */ +/* */ +/*===================================================================*/ +int pNesX_ReadRom( const char *pszFileName ) +{ +/* + * Read ROM image file + * + * Parameters + * const char *pszFileName (Read) + * + * Return values + * 0 : Normally + * -1 : Error + */ + FileHandle* file; + + /* Open ROM file */ + file = sd->open(pszFileName, O_RDONLY); + if ( file == NULL ) + { + printf("open error\r\n"); + return -1; + } + + /* Read ROM Header */ + file->read( &NesHeader, sizeof NesHeader); + if ( memcmp( NesHeader.byID, "NES\x1a", 4 ) != 0 ) + { + /* not .nes file */ + file->close(); + return -1; + } + + /* Clear SRAM */ + memset( SRAM, 0, SRAM_SIZE ); + + /* If trainer presents Read Triner at 0x7000-0x71ff */ + if ( NesHeader.byInfo1 & 4 ) + { + printf("Read Trainer\r\n"); + file->read( &SRAM[ 0x1000 ], 512 ); + } + + printf("RomSize: %d\r\n", NesHeader.byRomSize); + /* Allocate Memory for ROM Image */ + ROM = (BYTE *)malloc( NesHeader.byRomSize * 0x4000 ); + printf("ROM addr:%x\r\n", ROM); + + /* Read ROM Image */ + file->read( ROM, 0x4000 * NesHeader.byRomSize ); + + if ( NesHeader.byVRomSize > 0 ) + { + /* Allocate Memory for VROM Image */ + VROM = (BYTE *)malloc( NesHeader.byVRomSize * 0x2000 ); + printf("VROM addr:%x\r\n", VROM); + + /* Read VROM Image */ + file->read( VROM, 0x2000 * NesHeader.byVRomSize ); + } + + /* File close */ + file->close(); + + /* Successful */ + return 0; +} + +/*===================================================================*/ +/* */ +/* pNesX_ReleaseRom() : Release a memory for ROM */ +/* */ +/*===================================================================*/ +void pNesX_ReleaseRom() +{ +/* + * Release a memory for ROM + * + */ + if ( ROM ) + { + free( ROM ); + ROM = NULL; + } + + if ( VROM ) + { + free( VROM ); + VROM = NULL; + } +} + +/*===================================================================*/ +/* */ +/* pNesX_LoadFrame() : */ +/* Transfer the contents of work frame on the screen */ +/* */ +/*===================================================================*/ +void pNesX_LoadFrame() +{ +/* + * Transfer the contents of work frame on the screen + * + */ +#if defined(SHOW_FPS) + fps++; + + if (timer.read_ms() >= 1000) + { + timer.stop(); + printf("%d %d %d\r\n", fps, timer.read_ms(), dmawait); + fps = 0; + timer.reset(); + timer.start(); + } + dmawait = 0; +#endif +} + +void pNesX_TransmitLinedata() +{ + while (SpiHandle.State != HAL_SPI_STATE_READY) + { +#if defined(SHOW_FPS) + dmawait++; +#endif + } + HAL_SPI_Transmit_DMA(&SpiHandle, (uint8_t *)pDrawData, 256 * 2); +} + +#if !defined(PS_GAMEPAD) +const BYTE UsbPadTable[] = {0x10, 0x90, 0x80, 0xa0, 0x20, 0x60, 0x40, 0x50}; +#endif + +/*===================================================================*/ +/* */ +/* pNesX_PadState() : Get a joypad state */ +/* */ +/*===================================================================*/ +void pNesX_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem ) +{ +/* + * Get a joypad state + * + * Parameters + * DWORD *pdwPad1 (Write) + * Joypad 1 State R L D U St Se B A + * + * DWORD *pdwPad2 (Write) + * Joypad 2 State + * + * DWORD *pdwSystem (Write) + * Input for pNesX + * + */ + +#if !defined(PS_GAMEPAD) + *pdwPad1 = ((pad->report[4] & 0x20) >> 5) | + ((pad->report[4] & 0x10) >> 3) | + ((pad->report[5] & 0x30) >> 2); + + if (!(pad->report[4] & 8)) + { + *pdwPad1 |= UsbPadTable[pad->report[4] & 7]; + } + + *pdwPad1 = *pdwPad1 | ( *pdwPad1 << 8 ); + + *pdwPad2 = 0; + *pdwSystem = ((pad->report[5] & 0x4) >> 2) | + (((pad->report[5] & 0xa) == 0xa) << 1); + + USBHost::poll(); +#else + + unsigned short pad1, pad2; + pspad_read(&pad1, &pad2); + // R L D U St Se B A + + // SE -- -- ST U R D L L2 R2 L1 R1 TR O X SQ + *pdwPad1 = ((pad1 & 0x0400) >> 3) | + ((pad1 & 0x0100) >> 2) | + ((pad1 & 0x0200) >> 4) | + ((pad1 & 0x0800) >> 7) | + ((pad1 & 0x1000) >> 9) | + ((pad1 & 0x8000) >> 13) | + ((pad1 & 1) << 1) | + ((pad1 & 2) >> 1); + + *pdwPad1 = *pdwPad1 | ( *pdwPad1 << 8 ); + + *pdwPad2 = 0; + + *pdwSystem = ((pad1 & 0x80) >> 7) | + (((pad1 & 0x50) == 0x50) << 1); + +#endif + +} + +/*===================================================================*/ +/* */ +/* pNesX_MemoryCopy() : memcpy */ +/* */ +/*===================================================================*/ +void *pNesX_MemoryCopy( void *dest, const void *src, int count ) +{ +/* + * memcpy + * + * Parameters + * void *dest (Write) + * Points to the starting address of the copied block to destination + * + * const void *src (Read) + * Points to the starting address of the block of memory to copy + * + * int count (Read) + * Specifies the size, in bytes, of the block of memory to copy + * + * Return values + * Pointer of destination + */ + + memcpy(dest, src, count ); + return dest; +} + +/*===================================================================*/ +/* */ +/* pNesX_MemorySet() : */ +/* */ +/*===================================================================*/ +void *pNesX_MemorySet( void *dest, int c, int count ) +{ +/* + * memset + * + * Parameters + * void *dest (Write) + * Points to the starting address of the block of memory to fill + * + * int c (Read) + * Specifies the byte value with which to fill the memory block + * + * int count (Read) + * Specifies the size, in bytes, of the block of memory to fill + * + * Return values + * Pointer of destination + */ + + memset(dest, c, count); + return dest; +} + +/*===================================================================*/ +/* */ +/* DebugPrint() : Print debug message */ +/* */ +/*===================================================================*/ +void pNesX_DebugPrint( char *pszMsg ) +{ +} + +/*===================================================================*/ +/* */ +/* pNesX Initialise */ +/* */ +/*===================================================================*/ +int main() +{ + // TFT initialize + tft_init(); + tft_clear(TFT_BLACK); + tft_set_window(32, 8, NES_DISP_WIDTH + 32 - 1, NES_DISP_HEIGHT + 8 - 1); + + // SD card Initialize + sd = new SDFileSystem(PB_15, PB_14, PB_13, PA_9, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000); + sd->crc(true); + sd->large_frames(true); + sd->write_validation(true); + + strcpy(szRomFolder, "/sd"); + +#if !defined(PS_GAMEPAD) + // USB Gmaepad Initialize + pad = new USBHostGamepad(); + pad->connect(); +#else + pspad_init(); +#endif + + // Apu Initialize + ApuInit(); + + /*-------------------------------------------------------------------*/ + /* Start pNesX */ + /*-------------------------------------------------------------------*/ + + pNesX_Main(); +} + +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_Types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_Types.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,37 @@ +/*===================================================================*/ +/* */ +/* pNesX_Types.h : Type definitions for pNesX */ +/* */ +/* 1999/11/03 Racoon New preparation */ +/* */ +/*===================================================================*/ + +#ifndef PNESX_TYPES_H_INCLUDED +#define PNESX_TYPES_H_INCLUDED + +/*-------------------------------------------------------------------*/ +/* Type definition */ +/*-------------------------------------------------------------------*/ +#ifndef DWORD +typedef unsigned long DWORD; +#endif /* !DWORD */ + +#ifndef WORD +typedef unsigned short WORD; +#endif /* !WORD */ + +#ifndef BYTE +typedef unsigned char BYTE; +#endif /* !BYTE */ + +/*-------------------------------------------------------------------*/ +/* NULL definition */ +/*-------------------------------------------------------------------*/ +#ifndef NULL +#define NULL 0 +#endif /* !NULL */ + +#endif /* !PNESX_TYPES_H_INCLUDED */ + + +
diff -r 000000000000 -r 3dac1f1bc9e0 pNesX_logo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pNesX_logo.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,99 @@ +/*===================================================================*/ +/* */ +/* pNesX_logo.cpp : pNesX Logo image data(4bit bmp) */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ +extern const unsigned char pNesX_logo[]; + +const unsigned char pNesX_logo[] = +{ + 0x42,0x4D,0x4A,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0x00,0x00,0x00,0x28,0x00, + 0x00,0x00,0x63,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xB0,0xF8,0x00,0x2F,0xAD,0xF5,0x00,0x2D,0xA7, + 0xEC,0x00,0x2A,0x9C,0xDD,0x00,0x26,0x8A,0xC3,0x00,0x22,0x7A,0xAC,0x00,0x1B,0x5B, + 0x81,0x00,0x14,0x40,0x5A,0x00,0x0D,0x26,0x35,0x00,0x0B,0x18,0x20,0x00,0x09,0x11, + 0x16,0x00,0x08,0x0D,0x0F,0x00,0x08,0x08,0x08,0x00,0x9C,0xCC,0xC5,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xCC, + 0xC7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x5C,0xCC,0xC9,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xCC,0xCC,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xCC,0xCC,0x70,0x24,0x54, + 0x30,0x00,0x00,0x02,0x33,0x33,0x20,0x00,0x00,0x02,0x33,0x33,0x31,0x00,0x00,0x00, + 0x24,0x45,0x54,0x31,0x00,0x00,0x00,0x00,0x23,0x45,0x54,0x43,0x00,0x00,0x23,0x33, + 0x33,0x30,0x00,0x00,0x01,0x33,0x33,0x33,0x20,0x00,0x00,0x00,0x00,0x00,0x05,0xCC, + 0xCC,0x94,0x8B,0xCC,0x97,0x30,0x00,0x06,0x99,0x99,0x82,0x00,0x00,0x06,0x99,0x99, + 0x95,0x00,0x00,0x05,0x8A,0xCC,0xCB,0x98,0x62,0x00,0x00,0x15,0x8A,0xBC,0xCC,0xB9, + 0x74,0x00,0x48,0x99,0x99,0x95,0x00,0x00,0x03,0x89,0x99,0x99,0x60,0x00,0x00,0x00, + 0x00,0x00,0x03,0x9C,0xCC,0xCA,0xCC,0xCC,0xCC,0xA5,0x10,0x04,0xBC,0xCC,0xC5,0x00, + 0x00,0x18,0xCC,0xCC,0xC7,0x00,0x01,0x6C,0xCC,0xCC,0xCC,0xCC,0xC9,0x51,0x00,0x5B, + 0xCC,0xCC,0xCC,0xCC,0xCC,0x73,0x04,0x9C,0xCC,0xCA,0x41,0x00,0x05,0xCC,0xCC,0xCB, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xCC,0xCC,0xCC,0xCC,0xCC,0xCB,0x51,0x02, + 0x8C,0xCC,0xC7,0x10,0x00,0x4A,0xCC,0xCC,0xC9,0x20,0x03,0x9C,0xCC,0xCA,0x88,0xCC, + 0xCC,0xB6,0x10,0x7C,0xCC,0xCC,0x77,0x7B,0xCC,0xC7,0x20,0x49,0xCC,0xCC,0x94,0x00, + 0x06,0xCC,0xCC,0xC8,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0xCC,0xCC,0xC8,0x79, + 0xCC,0xCC,0xA4,0x00,0x6C,0xCC,0xC9,0x10,0x00,0x6C,0xCC,0xCC,0xCC,0x50,0x04,0xCC, + 0xCC,0xC5,0x22,0x59,0x99,0x87,0x30,0x69,0xCC,0xC8,0x20,0x15,0xBC,0xCC,0x60,0x04, + 0xAC,0xCC,0xC9,0x40,0x28,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29, + 0xCC,0xCC,0x92,0x02,0x7C,0xCC,0xC8,0x10,0x4C,0xCC,0xCC,0x50,0x02,0x8C,0xCC,0xCC, + 0xCC,0x71,0x05,0xCC,0xCC,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x44,0x11,0x35, + 0xAC,0xCC,0x91,0x00,0x49,0xCC,0xCC,0x94,0x3B,0xCC,0xCC,0xB4,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x17,0xCC,0xCC,0x80,0x00,0x39,0xCC,0xCB,0x40,0x28,0xCC,0xCC,0x70, + 0x04,0xBC,0xCC,0xCC,0xCC,0x93,0x03,0xBC,0xCC,0xC6,0x66,0x66,0x66,0x66,0x65,0x00, + 0x01,0x35,0x67,0x9C,0xCC,0xCC,0xC3,0x00,0x05,0x9C,0xCC,0xC8,0x6C,0xCC,0xCC,0x82, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xCC,0xCC,0x92,0x00,0x17,0xCC,0xCC,0x70, + 0x16,0xCC,0xCC,0x92,0x06,0xCC,0xCC,0xCC,0xCC,0xC5,0x02,0x8C,0xCC,0xCC,0xCC,0xCC, + 0xCC,0xCC,0xC7,0x10,0x06,0x9C,0xCC,0xCC,0xCC,0xCC,0xA2,0x00,0x00,0x5A,0xCC,0xCC, + 0xCC,0xCC,0xCC,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x8C,0xCC,0xC5,0x00, + 0x04,0xCC,0xCC,0x93,0x04,0xBC,0xCC,0xC5,0x18,0xCC,0xCC,0xCC,0xCC,0xC7,0x10,0x6C, + 0xCC,0xCC,0x99,0x99,0x9C,0xCC,0xCB,0x30,0x4B,0xCC,0xCC,0xCC,0xCC,0xC9,0x50,0x00, + 0x00,0x05,0x9C,0xCC,0xCC,0xCC,0xCC,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7C,0xCC,0xC8,0x30,0x04,0xBC,0xCC,0xB3,0x02,0x8C,0xCC,0xC7,0x4C,0xCC,0xCC,0x8C, + 0xCC,0xC9,0x30,0x39,0xCC,0xCA,0x53,0x33,0x39,0xCC,0xCC,0x40,0x5C,0xCC,0xCC,0xB9, + 0x87,0x63,0x10,0x00,0x00,0x00,0x59,0xCC,0xCC,0xCC,0xC9,0x20,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5C,0xCC,0xCC,0x74,0x16,0xCC,0xCC,0xC4,0x00,0x6C,0xCC,0xC8, + 0x7C,0xCC,0xCB,0x5C,0xCC,0xCC,0x50,0x06,0xCC,0xCC,0x82,0x00,0x29,0xCC,0xCC,0x50, + 0x4C,0xCC,0xC8,0x43,0x23,0x31,0x00,0x00,0x00,0x00,0x05,0xBC,0xCC,0xCC,0xC7,0x10, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xCC,0xCC,0xCC,0x9C,0xCC,0xCC,0xC4, + 0x00,0x4C,0xCC,0xCC,0xBC,0xCC,0xC8,0x28,0xCC,0xCC,0x70,0x01,0x7C,0xCC,0xC8,0x54, + 0x6C,0xCC,0xCC,0x40,0x07,0xCC,0xC8,0x42,0x38,0xCC,0x98,0x50,0x00,0x00,0x04,0xCC, + 0xCC,0xCC,0xCB,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xCC,0xCC,0xAC, + 0xCC,0xCC,0xCC,0x93,0x00,0x18,0xCC,0xCC,0xCC,0xCC,0xC6,0x16,0xCC,0xCC,0xA3,0x00, + 0x26,0xBC,0xCC,0xCC,0xCC,0xCC,0xC8,0x20,0x04,0x9C,0xCC,0xA8,0x9C,0xCC,0xCB,0x40, + 0x00,0x00,0x06,0xCC,0xCC,0xCC,0xCC,0xA5,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x05,0xCC,0xCC,0x77,0xCC,0xCC,0xCC,0x61,0x00,0x06,0xCC,0xCC,0xCC,0xCC,0xA4,0x03, + 0xAC,0xCC,0xC5,0x00,0x01,0x58,0xCC,0xCC,0xCC,0xCC,0x94,0x10,0x01,0x37,0xCC,0xCC, + 0xCC,0xCC,0xC7,0x20,0x00,0x00,0x08,0xCC,0xCC,0xCC,0xCC,0xCA,0x51,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x77,0x77,0x72,0x47,0x89,0x86,0x20,0x00,0x04,0xCC,0xCC, + 0xCC,0xCC,0x81,0x02,0x7C,0xCC,0xC7,0x10,0x00,0x01,0x57,0x89,0x98,0x76,0x30,0x00, + 0x00,0x00,0x46,0x79,0x99,0x87,0x62,0x00,0x00,0x00,0x3B,0xCC,0xCC,0x87,0xCC,0xCC, + 0xB5,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x8C,0xCC,0xCC,0xCC,0x60,0x00,0x6C,0xCC,0xC9,0x30,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xCC, + 0xCC,0x72,0x7C,0xCC,0xCA,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x6C,0xCC,0xCC,0xCC,0x30,0x00,0x4A,0xCC,0xCC,0x50, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x8C,0xCC,0xCC,0x50,0x38,0xCC,0xCC,0x94,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0xCC,0xCC,0xC8,0x10,0x00, + 0x08,0xCC,0xCC,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x03,0x9C,0xCC,0xCA,0x30,0x03,0x8C,0xCC,0xCA,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0xCC, + 0xCC,0xC6,0x00,0x00,0x06,0xCC,0xCC,0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xCC,0xCC,0xC8,0x20,0x00,0x49, + 0xCC,0xCC,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x88,0x88,0x83,0x00,0x00,0x03,0x88,0x88,0x84,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x88,0x88, + 0x86,0x00,0x00,0x14,0x88,0x88,0x87,0x30,0x00,0x00 +}; + +
diff -r 000000000000 -r 3dac1f1bc9e0 pspad.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pspad.cpp Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,44 @@ +/*===================================================================*/ +/* */ +/* pspad.cpp : PS Pad function */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ + +#include "mbed.h" +#include "pspad.h" + +// SPI interface +SPI pad_spi(PC_12, PC_11, PC_10); // MOSI(should pullup), MISO, SCK +DigitalOut pad1_cs(PD_2); + +// PS pad initialize +void pspad_init() +{ + pad_spi.format(8, 3); + pad_spi.frequency(250000); +} + +// Read PS Pad state +// data1 SE -- -- ST U R D L +// data2 L2 R2 L1 R1 TR O X SQ +void pspad_read(unsigned short *pad1, unsigned short *pad2) +{ + pad1_cs = 0; + wait_us(500); + + pad_spi.write(0x80); + pad_spi.write(0x42); + pad_spi.write(0); + pad_spi.write(0); + int d1 = pad_spi.write(0); + int d2 = pad_spi.write(0); + + pad1_cs = 1; + + *pad1 = (char)~d1 << 8 | (char)~d2; + + *pad2 = 0; +} +
diff -r 000000000000 -r 3dac1f1bc9e0 pspad.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pspad.h Sun Apr 03 07:45:29 2016 +0000 @@ -0,0 +1,19 @@ +/*===================================================================*/ +/* */ +/* pspad.h : PS Pad function header file */ +/* */ +/* 2016/1/20 Racoon */ +/* */ +/*===================================================================*/ +#ifndef PSPAD_H +#define PSPAD_H + +// Initialize interface +void pspad_init(); + +// Read PS Pad state +// SE -- -- ST U R D L L2 R2 L1 R1 TR O X SQ +void pspad_read(unsigned short *pad1, unsigned short *pad2); + +#endif +