test

Dependencies:   SDFileSystem mbed-dev

Fork of Nucleo_Ex06_EMU by woodstock .

Revision:
4:53ef91c87d74
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pNesX_System_Nucleo.cpp	Sat May 27 02:17:37 2017 +0000
@@ -0,0 +1,788 @@
+/*===================================================================*/
+/*                                                                   */
+/*  pNesX_System_Nucleo.cpp : The function which depends on a system */
+/*                         (for Nucleo F446RE)                       */
+/*                                                                   */
+/*  2016/1/20  Racoon                                                */
+/*                                                                   */
+/*===================================================================*/
+
+#define USE_CAN (1)
+
+/*-------------------------------------------------------------------*/
+/*  Include files                                                    */
+/*-------------------------------------------------------------------*/
+
+#include "mbed.h"
+#include "SDFileSystem.h"
+#include "tft.h"
+//#include "SWO.h"
+
+// added in for SD check
+int get_filelist ( char *path );
+
+// logo ptrs 
+
+extern const unsigned char l1_Logo[];
+extern const unsigned char asg_logo[];
+extern const unsigned char adaptable_conn_logo[];
+extern const unsigned char hacker_stickers_logo[];
+extern const unsigned char nostarch_logo[];
+extern const unsigned char nslmini[];
+extern const unsigned char PRO_LG_K_500x200_1CRevGrey_noDSCR[];
+extern const unsigned char securitysnobs[];
+extern const unsigned char supplyFrame[];
+extern const unsigned char WallOfSheep_logo_200px[];
+extern const unsigned char tinder_logo[];
+
+// ID that game pad data is sent on
+#define CAN_SEND_ID (0x7e1)
+
+// ID that game pad data is received from
+#define CAN_RECV_ID (0x7e0)
+
+// Memory interface
+enum {
+    CAN_READ_BYTE = CAN_SEND_ID + 1,
+    CAN_READ_WORD,
+    CAN_READ_DWORD,
+
+    CAN_WRITE_BYTE,
+    CAN_WRITE_WORD,
+    CAN_WRITE_DWORD
+};
+
+#ifdef USE_CAN
+
+CAN can1 ( PB_8, PB_9 );
+
+//not usng second CAN yet.,
+//CAN can2(PB_5, PB_6);
+
+#endif
+
+//#define ORIGINAL_GAMEPAD
+//#define PS_GAMEPAD
+#define NES_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 );
+
+// temporary store for joystick value
+static DWORD canval2;
+
+#ifdef USE_CAN
+// if there is a CAN msg available to read from
+static bool msgAvailable = false;
+#endif
+
+SDFileSystem *sd; //(PB_15, PB_14, PB_13, PA_9, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000);
+
+DigitalIn SW1 ( PC_13 );
+DigitalIn SW2 ( PC_14 );
+
+DigitalOut bLED1 ( PB_12 ) ;
+DigitalOut bLED2 ( PB_13 ) ;
+
+extern WORD LineData[][256];
+extern WORD *pDrawData;
+
+//#define SHOW_FPS
+
+#if defined(SHOW_FPS)
+Timer timer;
+int fps = 0;
+int dmawait;
+#endif
+
+//SWO_Channel swo;
+
+/*-------------------------------------------------------------------*/
+/*  ROM image file information                                       */
+/*-------------------------------------------------------------------*/
+
+extern char szRomFolder[];
+extern char szRomFilename[];
+extern char szRomPath[];
+
+char szRomName[ 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(ORIGINAL_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(ORIGINAL_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();
+
+#elif defined(NES_GAMEPAD)
+
+    *pdwSystem = 0 ;
+    *pdwPad1 = 0 ;
+    /*
+    01 02 03 04 05 06 07 08
+    -----------------------
+    01 80 80 7f 7f 0f 00 00
+    LEFT     00
+    RIGHT    FF
+    UP          00
+    DOWN        FF
+    SELECT            10
+    START             20
+    B              1F
+    A              2F
+    */
+
+    if ( pad->report[3] == 0x00 ) {*pdwPad1 |= KEYPAD_LEFT; *pdwSystem ^= PAD_SYS_LEFT;}
+
+    if ( pad->report[3] == 0xFF ) {*pdwPad1 |= KEYPAD_RIGHT; *pdwSystem ^= PAD_SYS_RIGHT;}
+
+    if ( pad->report[4] == 0x00 ) {*pdwPad1 |= KEYPAD_UP; *pdwSystem ^= PAD_SYS_UP;}
+
+    if ( pad->report[4] == 0xFF ) {*pdwPad1 |= KEYPAD_DOWN; *pdwSystem ^= PAD_SYS_DOWN;}
+
+    if ( pad->report[6] & 0x10 ) {*pdwPad1 |= KEYPAD_SELECT;}
+
+    if ( pad->report[6] & 0x20 ) {*pdwPad1 |= KEYPAD_START;}
+
+    if ( pad->report[5] & 0x10 ) {*pdwPad1 |= KEYPAD_B;}
+
+    if ( pad->report[5] & 0x20 ) {*pdwPad1 |= KEYPAD_A;}
+
+    if ( pad->report[6] == 0x30 ) { *pdwSystem = PAD_SYS_QUIT; }
+
+#ifdef USE_CAN
+
+    {
+        static DWORD lastpad;
+
+        if ( *pdwPad1 != lastpad ) {
+            can1.write ( CANMessage ( CAN_SEND_ID, ( char* ) pdwPad1, 4 ) );
+            lastpad = *pdwPad1;
+        }
+    }
+
+    if ( msgAvailable ) {
+
+        *pdwPad2 = canval2;
+
+    }   else
+#endif
+    {
+        // network ?
+        *pdwPad2 = 0;
+    }
+
+
+    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 )
+{
+}
+
+
+#ifdef USE_CAN
+
+/**
+ * @brief   'CAN receive-complete' interrup handler.
+ * @note    Called on arrival of new CAN message.
+ *          Keep it as short as possible.
+ * @param
+ * @retval
+ */
+void onMsgReceived()
+{
+    CANMessage msg;
+
+    // address to read/wrte
+    WORD    address;
+
+    // default to SRAM
+    uint8_t *bank_ptr = &RAM[0];
+    uint8_t bank = 0;
+
+    memset ( &msg, 0, sizeof ( msg ) );
+
+    if ( can1.read ( msg ) ) {
+
+        // less code
+        address = ( ( WORD ) msg.data[0] << 8 + ( WORD ) msg.data[1] );
+
+        // RAM,SRAM,ROM,ROMBANK0/1/2/3,PPURAM,VROM,PPUBANK
+        bank = msg.data[2];
+
+        // decide which bank
+        switch ( bank ) {
+            case 0:
+                //RAM
+                break;
+
+            case 1:
+                bank_ptr = &SRAM[0];
+                break;
+
+            case 2:
+                bank_ptr = ROM;
+                break;
+
+            case 3:
+                bank_ptr = &PPURAM[0];
+                break;
+
+            case 4:
+                bank_ptr = VROM;
+                break;
+
+            case 5:
+                bank_ptr = ( uint8_t* ) &PPUBANK[0];
+                break;
+
+            case 6:
+                bank_ptr = ( uint8_t* ) &SPRRAM[0];
+                break;
+
+        }
+
+        switch  ( msg.id  ) {
+            case CAN_RECV_ID :
+
+                /// so far only mark it as available when its a gamepad message..
+                msgAvailable = true;
+
+                //memcpy(&canval2,(char*)&msg.data[0],4);
+                canval2 = ( unsigned long ) ( msg.data[3] << 24 ) + ( ( unsigned long ) msg.data[2] << 16 ) + ( ( unsigned long ) msg.data[1] << 8 ) + ( ( unsigned long ) msg.data[0] );
+                break;
+
+            case CAN_READ_BYTE:
+                break;
+
+            case CAN_READ_WORD:
+                break;
+
+            case CAN_READ_DWORD:
+                break;
+
+            case CAN_WRITE_BYTE:
+                break;
+
+            case CAN_WRITE_WORD:
+                break;
+
+            case CAN_WRITE_DWORD:
+                break;
+        }
+    }
+}
+
+#endif
+
+
+const unsigned char * const logoPtrs[] = {
+    l1_Logo,
+
+//platinum
+    tinder_logo,
+    supplyFrame,
+    asg_logo,
+    nslmini,
+
+//gold
+    securitysnobs,
+
+//silver
+    PRO_LG_K_500x200_1CRevGrey_noDSCR,
+    adaptable_conn_logo,
+    WallOfSheep_logo_200px,
+    hacker_stickers_logo,
+    nostarch_logo
+};
+
+void draw_logos ( void )
+{
+    static unsigned char counter = 0;
+
+    unsigned short w;
+    unsigned char h;
+    const unsigned char *p;
+
+    for ( float b = 1 ; b > 0 ; b -= 0.05f )  {
+        backlight ( b );
+        HAL_Delay ( 20 );
+    }
+
+    backlight ( 0 );
+    tft_clear ( TFT_BLACK );
+
+    p = logoPtrs[counter];
+
+    w = ( unsigned short ) ( p[18] ) + ( ( unsigned short ) p[19] << 8 );
+    h = p[22];
+
+    draw_bmp_4bpp ( p, ( TFT_WIDTH / 2 ) - ( w / 2 ), ( ( TFT_HEIGHT / 2 ) - ( h / 2 ) ) );
+
+    for ( float b = 0 ; b < 1 ; b += 0.05f )  {
+        backlight ( b );
+        HAL_Delay ( 20 );
+    }
+
+
+    HAL_Delay ( 1000 );
+    counter++ ;
+
+    if ( counter >= sizeof ( logoPtrs ) / sizeof ( unsigned char * ) ) { counter = 0; }
+
+}
+
+
+/*===================================================================*/
+/*                                                                   */
+/*                pNesX Initialise                                   */
+/*                                                                   */
+/*===================================================================*/
+int main()
+{
+    const unsigned char *p ;
+    bLED1 = 0;
+    bLED2 = 0;
+
+#ifdef USE_CAN
+    //  can1.reset();
+    can1.frequency ( 1000000 );
+    can1.attach ( &onMsgReceived );              // attach 'CAN receive-complete' interrupt handler
+#endif
+
+    // TFT initialize
+    tft_init();
+
+    tft_set_window ( 32, 8, NES_DISP_WIDTH + 32 - 1, NES_DISP_HEIGHT + 8 - 1 );
+
+// SD_CS = PB_2
+// SD_SCK = PB_10
+// SD_MISO = PC_2
+// SD_MOSI = PC_3
+
+    if ( sd == NULL  ) 
+    {
+        // SD card Initialize
+    bLED2 = 1;
+
+        sd = new SDFileSystem ( PC_3, PC_2, PB_10, PB_2, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000 );
+
+
+        sd->crc ( true );
+        sd->large_frames ( true );
+        sd->write_validation ( true );
+
+        strcpy ( szRomFolder, "/sd" );
+
+    }
+
+    for ( ;; ) {
+        draw_logos();
+
+        if ( get_filelist ( "/sd" ) ) { break; }
+    }
+
+#if !defined(PS_GAMEPAD)
+    tft_clear ( TFT_RED + TFT_BLUE );
+    // USB Gamepad Initialize`
+    pad = new USBHostGamepad();
+    pad->connect();
+#else
+    pspad_init();
+#endif
+
+    // Apu Initialize
+    ApuInit();
+
+    /*-------------------------------------------------------------------*/
+    /*  Start pNesX                                                      */
+    /*-------------------------------------------------------------------*/
+
+    bLED2 = 1;
+    bLED1 = 1;
+
+    pNesX_Main();
+
+}
+
+