Last active
January 23, 2025 20:03
-
-
Save jamesxsc/8e2475cff2b950dcbade4c09e2465beb to your computer and use it in GitHub Desktop.
A test program leveraging inputs and outputs on the DE-10 FPGA development board running a NIOS2 soft processor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //#ifdef NOTDEF | |
| #include <sys/alt_stdio.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include "altera_avalon_pio_regs.h" | |
| #include "system.h" | |
| #define LED_MASK 0b0000001111111111 | |
| #define HEX_MASK 0b01111111 | |
| // Make usage of inputs more readable | |
| typedef union { | |
| struct { | |
| alt_u16 switch0 : 1; // Switch 0 | |
| alt_u16 switch1 : 1; // Switch 1 | |
| alt_u16 switch2 : 1; // Switch 2 | |
| alt_u16 switch3 : 1; // Switch 3 | |
| alt_u16 switch4 : 1; // Switch 4 | |
| alt_u16 switch5 : 1; // Switch 5 | |
| alt_u16 switch6 : 1; // Switch 6 | |
| alt_u16 switch7 : 1; // Switch 7 | |
| alt_u16 switch8 : 1; // Switch 8 | |
| alt_u16 switch9 : 1; // Switch 9 | |
| alt_u16 unused : 6; | |
| alt_u8 button0 : 1; // Button 0 | |
| alt_u8 button1 : 1; // Button 1 | |
| alt_u8 unused_2 : 6; | |
| } inputs; | |
| struct { | |
| alt_u16 pause : 1; // Master | |
| alt_u16 hex_edge : 1; // Pattern | |
| alt_u16 hex_long_edge : 1; // Modifier | |
| alt_u16 hex_random : 1; // Pattern | |
| alt_u16 variable_frequency : 1; // Master | |
| /// UNIMPLIMENTED FEATURES | |
| alt_u16 switch5 : 1; | |
| alt_u16 switch6 : 1; | |
| alt_u16 switch7 : 1; | |
| /// | |
| alt_u16 led_explosion : 1; // Pattern | |
| alt_u16 led_flash : 1; // Pattern | |
| alt_u16 unused : 6; | |
| alt_u8 highlight : 1; | |
| alt_u8 frequency : 1; | |
| alt_u8 unused_2 : 6; | |
| } settings; | |
| struct { | |
| alt_u16 switches; | |
| alt_u8 buttons; | |
| } raw; | |
| } settings_t; | |
| typedef struct { | |
| alt_u16 led; | |
| alt_u8 hex[6]; | |
| } output_t; | |
| typedef struct { | |
| alt_u8 hex_edge_index; | |
| alt_u8 variable_frequency_index; | |
| alt_u8 led_explosion_index; | |
| alt_u8 led_flash_on; | |
| } state_t; | |
| void set_settings(settings_t* settings, alt_u16 switch_datain, alt_u8 button_datain) | |
| { | |
| settings->raw.switches = switch_datain; | |
| settings->raw.buttons = button_datain; | |
| } | |
| void write_output(output_t output) | |
| { | |
| IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, output.led & LED_MASK); | |
| IOWR_ALTERA_AVALON_PIO_DATA(HEX0_BASE, ~output.hex[0] & HEX_MASK); | |
| IOWR_ALTERA_AVALON_PIO_DATA(HEX1_BASE, ~output.hex[1] & HEX_MASK); | |
| IOWR_ALTERA_AVALON_PIO_DATA(HEX2_BASE, ~output.hex[2] & HEX_MASK); | |
| IOWR_ALTERA_AVALON_PIO_DATA(HEX3_BASE, ~output.hex[3] & HEX_MASK); | |
| IOWR_ALTERA_AVALON_PIO_DATA(HEX4_BASE, ~output.hex[4] & HEX_MASK); | |
| IOWR_ALTERA_AVALON_PIO_DATA(HEX5_BASE, ~output.hex[5] & HEX_MASK); | |
| } | |
| alt_u16 variable_frequency_periods[] = {64,73,81,88,93,97,99,99,97,93,88,81,73,64,55,45,36,28,21,16,12,10,10,12,16,21,28,36,45,54}; // 10 - 100 - 10 sinusoidally | |
| alt_u16 led_explosion_values[] = { | |
| 0b0000000001111000, | |
| 0b0000000001111100, | |
| 0b0000000011111000, | |
| 0b0000000000110000, | |
| 0b0000000000010000, | |
| 0b0000000000100000, | |
| 0b0000000011001100, | |
| 0b0000001010000101, | |
| 0b0000001000000001, | |
| 0b0000000100000010, | |
| 0b0000000010000100, | |
| 0b0000000000110000, | |
| }; | |
| int main() | |
| { | |
| settings_t settings = {0}; | |
| output_t output = {0}; | |
| state_t state = {0}; | |
| long long ticks = 0; | |
| long long last_tap = 0; | |
| alt_u16 period = 100; //initial (ms) | |
| alt_u16 period_count = 0; | |
| // Main loop | |
| while (1) | |
| { | |
| // Delay | |
| alt_busy_sleep(1000); // 1ms should be slow enough to avoid debounce | |
| ticks++; | |
| // Obtain inputs (must be done in fast part of loop) | |
| alt_u16 switch_datain = IORD_ALTERA_AVALON_PIO_DATA(SWITCH_BASE) & 0b0000001111111111; | |
| alt_u8 button_datain = ~IORD_ALTERA_AVALON_PIO_DATA(BUTTON_BASE) & 0b0000000011; | |
| set_settings(&settings, switch_datain, button_datain); | |
| // Frequency set | |
| if (settings.settings.variable_frequency) | |
| { | |
| // Index is incremented in the slow clock | |
| period = variable_frequency_periods[state.variable_frequency_index]; | |
| } | |
| else if (settings.settings.frequency) | |
| { | |
| // Button tapped | |
| long long delta = ticks - last_tap; | |
| if (last_tap != 0 && delta > 1 && delta < 3000) // 3 seconds seems reasonable max period | |
| { | |
| period = delta; | |
| printf("\nSetting period %d", period); | |
| } | |
| last_tap = ticks; | |
| } | |
| if (period_count <= period) | |
| { | |
| ++period_count; | |
| continue; | |
| } | |
| /// Above is run every clock 1ms, below every period ms | |
| period_count = 0; | |
| // Update state | |
| if (!settings.settings.pause) | |
| { | |
| memset(&output, 0, sizeof(output)); | |
| // Variable frequency state | |
| state.variable_frequency_index = (state.variable_frequency_index + 1) % 30; | |
| // Highlight button | |
| if (settings.settings.highlight) | |
| { | |
| output.led = LED_MASK; | |
| for (int i = 0; i < 6; ++i) | |
| output.hex[i] = HEX_MASK; | |
| } | |
| // Hex edge pattern | |
| if (settings.settings.hex_edge) | |
| { | |
| // Increment state | |
| state.hex_edge_index = (state.hex_edge_index + 1) % 16; // There are 16 outer edge segments | |
| // Set output for this function | |
| for (alt_u8 i = 0; i < (settings.settings.hex_long_edge ? 6 : 2); ++i) | |
| { | |
| alt_u8 idx = (state.hex_edge_index + i) % 16; | |
| // 0-5 top; 6-11 bottom; 12-13 left; 14-15 right; | |
| // 0-5 top; 6-7 left; 8-13 bottom; 14-15 right; | |
| if (idx <= 5) output.hex[idx] |= 0b00000001; | |
| else if (idx <= 7) output.hex[5] |= 0b00010000 << (7 - idx); | |
| else if (idx <= 13) output.hex[13 - idx] |= 0b00001000; | |
| else output.hex[0] |= 0b00000010 << (15 - idx); | |
| } | |
| } | |
| // Random hex pattern | |
| if (settings.settings.hex_random) | |
| { | |
| alt_u8 idx = rand() % 6; | |
| output.hex[idx] = HEX_MASK; | |
| } | |
| // LED flash pattern | |
| if (settings.settings.led_flash) | |
| { | |
| if (!state.led_flash_on) | |
| { | |
| output.led |= LED_MASK; | |
| } | |
| state.led_flash_on = state.led_flash_on ^ 1; | |
| } | |
| if (settings.settings.led_explosion) | |
| { | |
| output.led |= led_explosion_values[state.led_explosion_index] & LED_MASK; | |
| state.led_explosion_index = (state.led_explosion_index + 1) % 12; | |
| } | |
| } | |
| // Write state to outputs | |
| write_output(output); | |
| } | |
| } | |
| //#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment