Ejemplo n.º 1
0
int Tape_GetNextBlock(void)
{
    while (pbTapeBlock < pbTapeImageEnd) { // loop until a valid block is found
#ifdef DEBUG_TAPE
        fprintf(pfoDebug, "--- New Block\r\n%02x\r\n", *pbTapeBlock);
#endif

        switch (*pbTapeBlock) {

        case 0x10: // standard speed data block
            dwTapeStage = TAPE_PILOT_STAGE; // block starts with a pilot tone
#ifdef DEBUG_TAPE
            fputs("--- PILOT\r\n", pfoDebug);
#endif
            dwTapePulseCycles = CYCLE_ADJUST(2168);
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
            dwTapePulseCount = 3220;
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
            return 1;

        case 0x11: // turbo loading data block
            dwTapeStage = TAPE_PILOT_STAGE; // block starts with a pilot tone
#ifdef DEBUG_TAPE
            fputs("--- PILOT\r\n", pfoDebug);
#endif
            dwTapePulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01));
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
            dwTapePulseCount = *(word *)(pbTapeBlock+0x01+0x0a);
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
            return 1;

        case 0x12: // pure tone
            dwTapeStage = TAPE_PILOT_STAGE; // block starts with a pilot tone
#ifdef DEBUG_TAPE
            fputs("--- TONE\r\n", pfoDebug);
#endif
            dwTapePulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01));
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
            dwTapePulseCount = *(word *)(pbTapeBlock+0x01+0x02);
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
            return 1;

        case 0x13: // sequence of pulses of different length
            dwTapeStage = TAPE_SYNC_STAGE;
#ifdef DEBUG_TAPE
            fputs("--- PULSE SEQ\r\n", pfoDebug);
#endif
            dwTapePulseCount = *(pbTapeBlock+0x01);
            pwTapePulseTable =
                pwTapePulseTablePtr = (word *)(pbTapeBlock+0x01+0x01);
            pwTapePulseTableEnd = pwTapePulseTable + dwTapePulseCount;
            Tape_GetCycleCount();
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
            return 1;

        case 0x14: // pure data block
            dwTapeStage = TAPE_DATA_STAGE;
#ifdef DEBUG_TAPE
            fputs("--- DATA\r\n", pfoDebug);
#endif
            dwTapeZeroPulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01)); // pulse length for a zero bit
            dwTapeOnePulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01+0x02)); // pulse length for a one bit
            dwTapeDataCount = ((*(dword *)(pbTapeBlock+0x01+0x07) & 0x00ffffff) - 1) << 3; // (byte count - 1) * 8 bits
            dwTapeDataCount += *(pbTapeBlock+0x01+0x04); // add the number of bits in the last data byte
            pbTapeBlockData = pbTapeBlock+0x01+0x0a; // pointer to the tape data
            dwTapeBitsToShift = 0;
            Tape_ReadDataBit(); // get the first bit of the first data byte
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
            return 1;

        case 0x15: // direct recording
            dwTapeStage = TAPE_SAMPLE_DATA_STAGE;
#ifdef DEBUG_TAPE
            fputs("--- SAMPLE DATA\r\n", pfoDebug);
#endif
            dwTapePulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01)); // number of T states per sample
            dwTapeDataCount = ((*(dword *)(pbTapeBlock+0x01+0x05) & 0x00ffffff) - 1) << 3; // (byte count - 1) * 8 bits
            dwTapeDataCount += *(pbTapeBlock+0x01+0x04); // add the number of bits in the last data byte
            pbTapeBlockData = pbTapeBlock+0x01+0x08; // pointer to the tape data
            dwTapeBitsToShift = 0;
            Tape_ReadSampleDataBit(); // get the first bit of the first data byte
            return 1;

        case 0x20: // pause
            if (*(word *)(pbTapeBlock+0x01)) { // was a pause requested?
                dwTapeStage = TAPE_PAUSE_STAGE;
#ifdef DEBUG_TAPE
                fputs("--- PAUSE\r\n", pfoDebug);
#endif
                dwTapePulseCycles = MS_TO_CYCLES(1); // start with a 1ms level opposite to the one last played
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
                dwTapePulseCycles = MS_TO_CYCLES(*(word *)(pbTapeBlock+0x01) - 1); // get the actual pause length
                dwTapePulseCount = 2; // just one pulse
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                return 1;
            }
            else {
                pbTapeBlock += 2 + 1; // skip block if pause length is 0
            }
            break;

        case 0x21: // group start
            pbTapeBlock += *(pbTapeBlock+0x01) + 1 + 1; // nothing to do, skip the block
            break;

        case 0x22: // group end
            pbTapeBlock += 1; // nothing to do, skip the block
            break;

        case 0x30: // text description
            pbTapeBlock += *(pbTapeBlock+0x01) + 1 + 1; // nothing to do, skip the block
            break;

        case 0x31: // message block
            pbTapeBlock += *(pbTapeBlock+0x01+0x01) + 2 + 1; // nothing to do, skip the block
            break;

        case 0x32: // archive info
            pbTapeBlock += *(word *)(pbTapeBlock+0x01) + 2 + 1; // nothing to do, skip the block
            break;

        case 0x33: // hardware type
            pbTapeBlock += (*(pbTapeBlock+0x01) * 3) + 1 + 1; // nothing to do, skip the block
            break;

        case 0x34: // emulation info
            pbTapeBlock += 8 + 1; // nothing to do, skip the block
            break;

        case 0x35: // custom info block
            pbTapeBlock += *(dword *)(pbTapeBlock+0x01+0x10) + 0x14 + 1; // nothing to do, skip the block
            break;

        case 0x40: // snapshot block
            pbTapeBlock += (*(dword *)(pbTapeBlock+0x01+0x01) & 0x00ffffff) + 0x04 + 1; // nothing to do, skip the block
            break;

        case 0x5A: // another tzx/cdt file
            pbTapeBlock += 9 + 1; // nothing to do, skip the block
            break;

        default: // "extension rule"
            pbTapeBlock += *(dword *)(pbTapeBlock+0x01) + 4 + 1; // nothing to do, skip the block
        }
    }

    return 0; // we've reached the end of the image
}
Ejemplo n.º 2
0
void Tape_UpdateLevel(void)
{
    switch (dwTapeStage) {

    case TAPE_PILOT_STAGE:
        Tape_SwitchLevel();
        dwTapePulseCount--;
        if (dwTapePulseCount > 0) { // is the pilot tone still playing?
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
        }
        else { // finished with the pilot tone
            switch (*pbTapeBlock) {

            case 0x10: // standard speed data block
                dwTapeStage = TAPE_SYNC_STAGE;
#ifdef DEBUG_TAPE
                fputs("--- SYNC\r\n", pfoDebug);
#endif
                wCycleTable[0] = 667;
                wCycleTable[1] = 735;
                pwTapePulseTable =
                    pwTapePulseTablePtr = &wCycleTable[0];
                pwTapePulseTableEnd = &wCycleTable[2];
                Tape_GetCycleCount();
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                dwTapePulseCount = 2;
                break;

            case 0x11: // turbo loading data block
                dwTapeStage = TAPE_SYNC_STAGE;
#ifdef DEBUG_TAPE
                fputs("--- SYNC\r\n", pfoDebug);
#endif
                pwTapePulseTable =
                    pwTapePulseTablePtr = (word *)(pbTapeBlock+0x01+0x02);
                pwTapePulseTableEnd = (word *)(pbTapeBlock+0x01+0x06);
                Tape_GetCycleCount();
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                dwTapePulseCount = 2;
                break;

            case 0x12: // pure tone
                Tape_BlockDone();
                break;
            }
        }
        break;

    case TAPE_SYNC_STAGE:
        Tape_SwitchLevel();
        dwTapePulseCount--;
        if (dwTapePulseCount > 0) {
            Tape_GetCycleCount();
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
        }
        else {
            switch (*pbTapeBlock) {

            case 0x10: // standard speed data block
                dwTapeStage = TAPE_DATA_STAGE;
#ifdef DEBUG_TAPE
                fputs("--- DATA\r\n", pfoDebug);
#endif
                dwTapeZeroPulseCycles = CYCLE_ADJUST(855); // pulse length for a zero bit
                dwTapeOnePulseCycles = CYCLE_ADJUST(1710); // pulse length for a one bit
                dwTapeDataCount = *(word *)(pbTapeBlock+0x01+0x02) << 3; // byte count * 8 bits;
                pbTapeBlockData = pbTapeBlock+0x01+0x04; // pointer to the tape data
                dwTapeBitsToShift = 0;
                Tape_ReadDataBit();
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                break;

            case 0x11: // turbo loading data block
                dwTapeStage = TAPE_DATA_STAGE;
#ifdef DEBUG_TAPE
                fputs("--- DATA\r\n", pfoDebug);
#endif
                dwTapeZeroPulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01+0x06)); // pulse length for a zero bit
                dwTapeOnePulseCycles = CYCLE_ADJUST(*(word *)(pbTapeBlock+0x01+0x08)); // pulse length for a one bit
                dwTapeDataCount = ((*(dword *)(pbTapeBlock+0x01+0x0f) & 0x00ffffff) - 1) << 3; // (byte count - 1) * 8 bits;
                dwTapeDataCount += *(pbTapeBlock+0x01+0x0c); // add the number of bits in the last data byte
                pbTapeBlockData = pbTapeBlock+0x01+0x12; // pointer to the tape data
                dwTapeBitsToShift = 0;
                Tape_ReadDataBit();
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                break;

            case 0x13: // sequence of pulses of different length
                Tape_BlockDone();
                break;
            }
        }
        break;

    case TAPE_DATA_STAGE:
        Tape_SwitchLevel();
        dwTapePulseCount--;
        if (dwTapePulseCount > 0) {
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
        }
        else {
            if (Tape_ReadDataBit()) {
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
            }
            else {
                switch (*pbTapeBlock) {

                case 0x10: // standard speed data block
                    if (*(word *)(pbTapeBlock+0x01)) { // was a pause requested?
                        dwTapeStage = TAPE_PAUSE_STAGE;
#ifdef DEBUG_TAPE
                        fputs("--- PAUSE\r\n", pfoDebug);
#endif
                        dwTapePulseCycles = MS_TO_CYCLES(1); // start with a 1ms level opposite to the one last played
                        iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                        fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                        dwTapePulseCycles = MS_TO_CYCLES(*(word *)(pbTapeBlock+0x01) - 1); // pause in ms
                        dwTapePulseCount = 2; // just one pulse
                    }
                    else {
                        Tape_BlockDone();
                    }
                    break;

                case 0x11: // turbo loading data block
                    if (*(word *)(pbTapeBlock+0x01+0x0d)) { // was a pause requested?
                        dwTapeStage = TAPE_PAUSE_STAGE;
#ifdef DEBUG_TAPE
                        fputs("--- PAUSE\r\n", pfoDebug);
#endif
                        dwTapePulseCycles = MS_TO_CYCLES(1); // start with a 1ms level opposite to the one last played
                        iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                        fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                        dwTapePulseCycles = MS_TO_CYCLES(*(word *)(pbTapeBlock+0x01+0x0d) - 1); // pause in ms
                        dwTapePulseCount = 2; // just one pulse
                    }
                    else {
                        Tape_BlockDone();
                    }
                    break;

                case 0x14: // pure data block
                    if (*(word *)(pbTapeBlock+0x01+0x05)) { // was a pause requested?
                        dwTapeStage = TAPE_PAUSE_STAGE;
#ifdef DEBUG_TAPE
                        fputs("--- PAUSE\r\n", pfoDebug);
#endif
                        dwTapePulseCycles = MS_TO_CYCLES(1); // start with a 1ms level opposite to the one last played
                        iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                        fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                        dwTapePulseCycles = MS_TO_CYCLES(*(word *)(pbTapeBlock+0x01+0x05) - 1); // pause in ms
                        dwTapePulseCount = 2; // just one pulse
                    }
                    else {
                        Tape_BlockDone();
                    }
                    break;

                default:
                    Tape_BlockDone();
                }
            }
        }
        break;

    case TAPE_SAMPLE_DATA_STAGE:
        if (!Tape_ReadSampleDataBit()) {
            if (*(word *)(pbTapeBlock+0x01+0x02)) { // was a pause requested?
                dwTapeStage = TAPE_PAUSE_STAGE;
#ifdef DEBUG_TAPE
                fputs("--- PAUSE\r\n", pfoDebug);
#endif
                dwTapePulseCycles = MS_TO_CYCLES(1); // start with a 1ms level opposite to the one last played
                iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
                fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
                dwTapePulseCycles = MS_TO_CYCLES(*(word *)(pbTapeBlock+0x01+0x02) - 1); // pause in ms
                dwTapePulseCount = 2; // just one pulse
            }
            else {
                Tape_BlockDone();
            }
        }
        break;

    case TAPE_PAUSE_STAGE:
        bTapeLevel = TAPE_LEVEL_LOW;
        dwTapePulseCount--;
        if (dwTapePulseCount > 0) {
            iTapeCycleCount += (int)dwTapePulseCycles; // set cycle count for current level
#ifdef DEBUG_TAPE
            fprintf(pfoDebug, "%c %d\r\n",(bTapeLevel == TAPE_LEVEL_HIGH ? 'H':'L'), iTapeCycleCount);
#endif
        }
        else {
            Tape_BlockDone();
        }
        break;

    case TAPE_END:
        CPC.tape_play_button = 0;
        break;
    }
}
Ejemplo n.º 3
0
static unsigned long wait_mode_power_down_hook( unsigned long delay_ms )
{
    bool jtag_enabled       = ( ( CoreDebug ->DHCSR & CoreDebug_DEMCR_TRCENA_Msk ) != 0 ) ? true : false;
    bool jtag_delay_elapsed = ( mico_get_time() > JTAG_DEBUG_SLEEP_DELAY_MS ) ? true : false;
    uint32_t     elapsed_cycles     = 0;

    /* Criteria to enter WAIT mode
     * 1. Clock needed counter is 0 and no JTAG debugging
     * 2. Clock needed counter is 0, in JTAG debugging session, and MiCO system tick has progressed over 3 seconds.
     *    This is to give OpenOCD enough time to poke the JTAG tap before the CPU enters WAIT mode.
     */
    if ( ( samg5x_clock_needed_counter == 0 ) && ( ( jtag_enabled == false ) || ( ( jtag_enabled == true ) && ( jtag_delay_elapsed == true ) ) ) )
    {
        uint32_t total_sleep_cycles;
        uint32_t total_delay_cycles;

        /* Start real-time timer */
        rtt_init( RTT, RTT_CLOCK_PRESCALER );

        /* Start atomic operation */
        DISABLE_INTERRUPTS;

        /* Ensure deep sleep bit is enabled, otherwise system doesn't go into deep sleep */
        SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

        /* Disable SysTick */
        SysTick->CTRL &= ( ~( SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk ) );

        /* End atomic operation */
        ENABLE_INTERRUPTS;

        /* Expected total time CPU executing in this function (including WAIT mode time) */
        total_sleep_cycles = MS_TO_CYCLES( delay_ms );

        /* Total cycles in WAIT mode loop */
        total_delay_cycles = ( total_sleep_cycles / RTT_MAX_CYCLES + 1 ) * RC_OSC_DELAY_CYCLES + WAIT_MODE_ENTER_DELAY_CYCLES + WAIT_MODE_EXIT_DELAY_CYCLES;

        if ( total_sleep_cycles > total_delay_cycles )
        {
            /* Adjust total sleep cycle to exclude exit delay */
            total_sleep_cycles -= WAIT_MODE_EXIT_DELAY_CYCLES;

            /* Prepare platform specific settings before entering powersave */
//            platform_enter_powersave();

            ///* Prepare WLAN bus before entering powersave */
            //platform_bus_enter_powersave();

            /* Disable brownout detector */
            supc_disable_brownout_detector( SUPC );

            /* Backup system I/0 functions and set all to GPIO to save power */
            system_io_backup_value = matrix_get_system_io();
            matrix_set_system_io( 0x0CF0 );

            /* Switch Master Clock to Main Clock (internal fast RC oscillator) */
            pmc_switch_mck_to_mainck( PMC_PCK_PRES_CLK_1 );

            /* Switch on internal fast RC oscillator, switch Main Clock source to internal fast RC oscillator and disables external fast crystal */
            pmc_switch_mainck_to_fastrc( CKGR_MOR_MOSCRCF_8_MHz );

            /* Disable external fast crystal */
            pmc_osc_disable_xtal( 0 );

            /* Disable PLLA */
            pmc_disable_pllack( );

            /* This above process introduces certain delay. Add delay to the elapsed cycles */
            elapsed_cycles += rtt_read_timer_value( RTT );

            while ( wake_up_interrupt_triggered == false  && elapsed_cycles < total_sleep_cycles )
            {
                uint32_t current_sleep_cycles = total_sleep_cycles - elapsed_cycles;

                /* Start real-time timer and alarm */
                rtt_init( RTT, RTT_CLOCK_PRESCALER );
                rtt_write_alarm_time( RTT, ( current_sleep_cycles > RTT_MAX_CYCLES ) ? RTT_MAX_CYCLES - RC_OSC_DELAY_CYCLES : current_sleep_cycles - RC_OSC_DELAY_CYCLES );

                __asm("wfi");
                /* Enter WAIT mode */
                //pmc_enable_waitmode();

                /* Clear wake-up status */
                rtt_get_status( RTT );

                /* Add sleep time to the elapsed cycles */
                elapsed_cycles += rtt_read_timer_value( RTT );
            }

            /* Re-enable real-time timer to time clock reinitialisation delay */
            rtt_init( RTT, RTT_CLOCK_PRESCALER );

            /* Reinit fast clock. This takes ~19ms, but the timing has been compensated */
            init_clocks();

            /* Disable unused clock to save power */
            pmc_osc_disable_fastrc();

            /* Restore system I/O pins */
            matrix_set_system_io( system_io_backup_value );

            /* Restore WLAN bus */
            //platform_bus_exit_powersave();

//            /* Restore platform-specific settings */
//            platform_exit_powersave();

            /* Add clock reinitialisation delay to elapsed cycles */
            elapsed_cycles += rtt_read_timer_value( RTT );

            /* Disable RTT to save power */
            RTT->RTT_MR = (uint32_t)( 1 << 20 );
        }
    }

    /* Start atomic operation */
    DISABLE_INTERRUPTS;

    /* Switch SysTick back on */
    SysTick->CTRL |= ( SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk );

    /* Clear flag indicating interrupt triggered by wake up pin */
    wake_up_interrupt_triggered = false;

    /* End atomic operation */
    ENABLE_INTERRUPTS;

    /* Return total time in milliseconds */
    return CYCLES_TO_MS( elapsed_cycles );
}