Using the Front Panel Switches in Magic‐1 - retrotruestory/M1DEV GitHub Wiki
Using the Front Panel Switches in Magic-1
Hardware Interface
The front panel switches in Magic-1 are memory-mapped at address 0xFFA0
, allowing direct access from software:
// Define the switches address
#define SWITCHES_BASE 0xFFA0
// Read the current switch positions
uint8_t read_front_panel() {
return *(volatile uint8_t*)SWITCHES_BASE;
}
Each bit in the read value represents the state of one switch (0 = off, 1 = on).
Software Interface
The Magic-1 bootloader includes a built-in function to read the switches:
// Read the front panel switches
uint8_t switch_value = read_switches();
Common Usage Patterns
1. Boot Control
// Wait for switch input before continuing boot
if (pause_before_boot) {
uart_puts("Set switches and press any key to continue...\r\n");
while (read_switches() == 0); // Wait until any switch is set
}
// Select boot image based on switches
int boot_image = read_switches() & 0x07; // Lower 3 bits for image selection (0-7)
2. Debugging Options
// Check switch configuration for debug options
if (read_switches() & 0x01) {
// Switch 0 enables verbose output
debug_level = DEBUG_VERBOSE;
}
if (read_switches() & 0x02) {
// Switch 1 enables memory diagnostics
run_memory_test();
}
if (read_switches() & 0x04) {
// Switch 2 enables execution tracing
enable_execution_trace();
}
3. Runtime Configuration
// Select operating mode based on switches
uint8_t mode = read_switches() & 0x0F; // Lower 4 bits for mode selection
switch (mode) {
case 1: start_terminal_mode(); break;
case 2: start_monitor_mode(); break;
case 4: start_diagnostic_mode(); break;
case 8: start_network_mode(); break;
default: start_normal_mode(); break;
}
4. Program Execution Control
// Use switches to control execution or debugging
void debug_loop() {
while (1) {
uint8_t switches = read_switches();
if (switches & 0x01) step_instruction(); // Execute single instruction
if (switches & 0x02) dump_registers(); // Display registers
if (switches & 0x04) dump_memory(mem_addr); // Display memory
if (switches & 0x08) continue_execution(); // Continue normal execution
if (switches & 0x10) break; // Exit debug loop
}
}
Important Information for Programmers
-
Read Frequency: Switches can be read at any time without impacting system performance (fast access to mapped memory)
-
Switch Debouncing: Mechanical switches may exhibit contact bounce, so debouncing techniques are recommended:
// Simple debounce implementation uint8_t debounce_switches() { uint8_t val1 = read_switches(); // Small delay for (volatile int i = 0; i < 1000; i++); uint8_t val2 = read_switches(); return (val1 & val2); // Return only switches that are stable }
-
Switch Masking: Often used to isolate specific bits:
// Check only specific switches uint8_t check_specific_switches() { uint8_t switches = read_switches(); uint8_t mask = 0x03; // Only interested in bits 0 and 1 return (switches & mask); }
-
State Change Detection:
// Detect changes in switch states uint8_t last_state = 0; void check_switch_changes() { uint8_t current = read_switches(); uint8_t changed = current ^ last_state; if (changed) { // Switches have changed uart_puts("Switches changed: "); uart_puthex(changed); uart_puts("\r\n"); } last_state = current; }
-
Use in Interrupt Handlers: Switches can be safely read in interrupt handlers since access is fast and requires no additional synchronization.
The front panel switches provide a simple yet powerful mechanism for interacting with the Magic-1 system without requiring keyboard input, which is particularly useful during early boot phases or hardware debugging.