Skip to content

Instantly share code, notes, and snippets.

@jamesxsc
Last active January 23, 2025 20:03
Show Gist options
  • Select an option

  • Save jamesxsc/8e2475cff2b950dcbade4c09e2465beb to your computer and use it in GitHub Desktop.

Select an option

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
//#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