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 }
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; } }
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 ); }