int main() { XStatus status; u16 sw, oldSw =0xFFFF; // 0xFFFF is invalid --> makes sure the PWM freq is updated 1st time int rotcnt, oldRotcnt = 0x1000; bool done = false; bool hw_switch = 0; init_platform(); // initialize devices and set up interrupts, etc. status = do_init(); if (status != XST_SUCCESS) { PMDIO_LCD_setcursor(1,0); PMDIO_LCD_wrstring("****** ERROR *******"); PMDIO_LCD_setcursor(2,0); PMDIO_LCD_wrstring("INIT FAILED- EXITING"); exit(XST_FAILURE); } // initialize the global variables timestamp = 0; pwm_freq = INITIAL_FREQUENCY; pwm_duty = INITIAL_DUTY_CYCLE; clkfit = 0; new_perduty = false; // start the PWM timer and kick of the processing by enabling the Microblaze interrupt PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty); PWM_Start(&PWMTimerInst); microblaze_enable_interrupts(); // display the greeting PMDIO_LCD_setcursor(1,0); PMDIO_LCD_wrstring("ECE544 Project 1"); PMDIO_LCD_setcursor(2,0); PMDIO_LCD_wrstring(" by Rehan Iqbal "); NX4IO_setLEDs(0x0000FFFF); delay_msecs(2000); NX4IO_setLEDs(0x00000000); // write the static text to the display PMDIO_LCD_clrd(); PMDIO_LCD_setcursor(1,0); PMDIO_LCD_wrstring("G|FR: DCY: %"); PMDIO_LCD_setcursor(2,0); PMDIO_LCD_wrstring("D|FR: DCY: %"); // turn off the LEDs and clear the seven segment display NX4IO_setLEDs(0x00000000); NX410_SSEG_setAllDigits(SSEGLO, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE); NX410_SSEG_setAllDigits(SSEGHI, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE); // main loop do { // check rotary encoder pushbutton to see if it's time to quit if (PMDIO_ROT_isBtnPressed()) { done = true; } else { new_perduty = false; // get the switches and mask out all but the switches that determine the PWM timer frequency sw &= PWM_FREQ_MSK; sw = NX4IO_getSwitches(); if (sw != oldSw) { // check the status of sw[2:0] and assign appropriate PWM output frequency switch (sw & 0x07) { case 0x00: pwm_freq = PWM_FREQ_100HZ; break; case 0x01: pwm_freq = PWM_FREQ_1KHZ; break; case 0x02: pwm_freq = PWM_FREQ_10KHZ; break; case 0x03: pwm_freq = PWM_FREQ_50KHZ; break; case 0x04: pwm_freq = PWM_FREQ_100KHZ; break; case 0x05: pwm_freq = PWM_FREQ_500KHZ; break; case 0x06: pwm_freq = PWM_FREQ_1MHZ; break; case 0x07: pwm_freq = PWM_FREQ_5MHZ; break; } // check the status of sw[3] and assign to global variable hw_switch = (sw & 0x08); // update global variable indicating there are new changes oldSw = sw; new_perduty = true; } // read rotary count and handle duty cycle changes // limit duty cycle to 0% to 99% PMDIO_ROT_readRotcnt(&rotcnt); if (rotcnt != oldRotcnt) { // show the rotary count in hex on the seven segment display NX4IO_SSEG_putU16Hex(SSEGLO, rotcnt); // change the duty cycle pwm_duty = MAX(1, MIN(rotcnt, 99)); oldRotcnt = rotcnt; new_perduty = true; } // update generated frequency and duty cycle if (new_perduty) { u32 freq, dutycycle; unsigned int detect_freq = 0x00; unsigned int detect_duty = 0x00; // set the new PWM parameters - PWM_SetParams stops the timer status = PWM_SetParams(&PWMTimerInst, pwm_freq, pwm_duty); if (status == XST_SUCCESS) { PWM_GetParams(&PWMTimerInst, &freq, &dutycycle); update_lcd(freq, dutycycle, 1); // check if sw[3] is high or low (HWDET / SWDET) // pass functions different args depending on which mode is selected if (hw_switch) { detect_freq = calc_freq(hw_high_count, hw_low_count, hw_switch); detect_duty = calc_duty(hw_high_count, hw_low_count); } else { detect_freq = calc_freq(sw_high_count, sw_low_count, hw_switch); detect_duty = calc_duty(sw_high_count, sw_low_count); } // update the LCD display with detected frequency & duty cycle update_lcd(detect_freq, detect_duty, 2); PWM_Start(&PWMTimerInst); } } } } while (!done); // wait until rotary encoder button is released do { delay_msecs(10); } while (PMDIO_ROT_isBtnPressed()); // we're done, say goodbye xil_printf("\nThat's All Folks!\n\n"); PMDIO_LCD_setcursor(1,0); PMDIO_LCD_wrstring("That's All Folks"); PMDIO_LCD_setcursor(2,0); PMDIO_LCD_wrstring(" "); NX410_SSEG_setAllDigits(SSEGHI, CC_BLANK, CC_B, CC_LCY, CC_E, DP_NONE); NX410_SSEG_setAllDigits(SSEGLO, CC_B, CC_LCY, CC_E, CC_BLANK, DP_NONE); delay_msecs(5000); // turn the lights out PMDIO_LCD_clrd(); NX410_SSEG_setAllDigits(SSEGHI, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE); NX410_SSEG_setAllDigits(SSEGLO, CC_BLANK, CC_BLANK, CC_BLANK, CC_BLANK, DP_NONE); NX4IO_RGBLED_setDutyCycle(RGB1, 0, 0, 0); NX4IO_RGBLED_setChnlEn(RGB1, false, false, false); // exit gracefully cleanup_platform(); exit(0); }
int do_init(void) { int status; // status from Xilinx Lib calls // initialize the Nexys4IO and Pmod544IO hardware and drivers // rotary encoder is set to increment from 0 by DUTY_CYCLE_CHANGE status = NX4IO_initialize(NX4IO_BASEADDR); if (status != XST_SUCCESS) { return XST_FAILURE; } status = PMDIO_initialize(PMDIO_BASEADDR); if (status != XST_SUCCESS) { return XST_FAILURE; } // successful initialization. Set the rotary encoder // to increment from 0 by DUTY_CYCLE_CHANGE counts per rotation PMDIO_ROT_init(DUTY_CYCLE_CHANGE, true); PMDIO_ROT_clear(); // initialize the GPIO instances status = XGpio_Initialize(&GPIOInst0, GPIO_0_DEVICE_ID); if (status != XST_SUCCESS) { return XST_FAILURE; } status = XGpio_Initialize(&GPIOInst1, GPIO_1_DEVICE_ID); if (status != XST_SUCCESS) { return XST_FAILURE; } // GPIO_0 channel 1 is an 8-bit input port. bit[7:1] = reserved, bit[0] = PWM output (for duty cycle calculation) // GPIO_0 channel 2 is an 8-bit output port. bit[7:1] = reserved, bit[0] = FIT clock XGpio_SetDataDirection(&GPIOInst0, GPIO_0_INPUT_CHANNEL, 0xFF); XGpio_SetDataDirection(&GPIOInst0, GPIO_0_OUTPUT_CHANNEL, 0xFE); // GPIO_1 channel 1 is a 32-bit input port - used to pass hw_detect 'high' count to application // GPIO_1 channel 2 is an 8-bit output port - used to pass hw_detect 'low' count to application XGpio_SetDataDirection(&GPIOInst1, GPIO_1_HIGH_COUNT, 0xFFFFFFFF); XGpio_SetDataDirection(&GPIOInst1, GPIO_1_LOW_COUNT, 0xFFFFFFFF); // initialize the PWM timer/counter instance but do not start it // do not enable PWM interrupts. Clock frequency is the AXI clock frequency status = PWM_Initialize(&PWMTimerInst, PWM_TIMER_DEVICE_ID, false, AXI_CLOCK_FREQ_HZ); if (status != XST_SUCCESS) { return XST_FAILURE; } // initialize the interrupt controller status = XIntc_Initialize(&IntrptCtlrInst, INTC_DEVICE_ID); if (status != XST_SUCCESS) { return XST_FAILURE; } // connect the fixed interval timer (FIT) handler to the interrupt status = XIntc_Connect(&IntrptCtlrInst, FIT_INTERRUPT_ID, (XInterruptHandler)FIT_Handler, (void *)0); if (status != XST_SUCCESS) { return XST_FAILURE; } // start the interrupt controller such that interrupts are enabled for // all devices that cause interrupts status = XIntc_Start(&IntrptCtlrInst, XIN_REAL_MODE); if (status != XST_SUCCESS) { return XST_FAILURE; } // enable the FIT interrupt XIntc_Enable(&IntrptCtlrInst, FIT_INTERRUPT_ID); // set the duty cycles for RGB1. The channels will be enabled/disabled // in the FIT interrupt handler. Red and Blue make purple NX4IO_RGBLED_setDutyCycle(RGB1, 64, 0, 64); NX4IO_RGBLED_setChnlEn(RGB1, false, false, false); return XST_SUCCESS; }
XStatus init_axi_devices(void) { int status; // INITIALIZE : Nexys4IO status = NX4IO_initialize(XPAR_NEXYS4IO_0_S00_AXI_BASEADDR); if (status != XST_SUCCESS) return XST_FAILURE; NX4IO_setLEDs(0x0000FFFF); // INITIALIZE : PMOD544IO status = PMDIO_initialize(XPAR_PMOD544IOR2_0_S00_AXI_BASEADDR); if (status != XST_SUCCESS) return XST_FAILURE; // SET : Encoder val = 0, increment val = DUTY_CYCLE_CHANGE NX4IO_setLEDs(0x0000FFFE); PMDIO_ROT_init(DUTY_CYCLE_INCREMENTS, true); PMDIO_ROT_clear(); NX4IO_setLEDs(0x0000FFFD); // This is currently crashing the program =/ // No GPIO for now // INITIALIZE : Degug signal GPIO (1X 4-bit) /*status = XGpio_Initialize(&instGPIODebug, XPAR_AXI_GPIO_0_BASEADDR);*/ /*if (status != XST_SUCCESS) return XST_FAILURE;*/ /*NX4IO_setLEDs(0x0000FFFC);*/ /*// SET : Direction of output ports */ /*XGpio_SetDataDirection(&instGPIODebug, 0, 0xFFFFFFF0);*/ /*NX4IO_setLEDs(0x0000FFFB);*/ // INITIALIZE : PWM timer/counter status = PWM_Initialize(&instPWMTimer, XPAR_AXI_TIMER_0_DEVICE_ID, false, XPAR_CPU_CORE_CLOCK_FREQ_HZ); if (status != XST_SUCCESS) return XST_FAILURE; NX4IO_setLEDs(0x0000FFFA); // INITIALIZE : Interrupt controller status = XIntc_Initialize(&instIntrCtrl, XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID); if (status != XST_SUCCESS) return XST_FAILURE; NX4IO_setLEDs(0x0000FFF9); // SET : GPIO handler to interrupt vector status = XIntc_Connect(&instIntrCtrl, XPAR_MICROBLAZE_0_AXI_INTC_FIT_TIMER_0_INTERRUPT_INTR, (XInterruptHandler)FIT_Handler, (void *)0); if (status != XST_SUCCESS) return XST_FAILURE; NX4IO_setLEDs(0x0000FFF8); // SET : Interrupt controller enabled for all devices status = XIntc_Start(&instIntrCtrl, XIN_REAL_MODE); if (status != XST_SUCCESS) return XST_FAILURE; NX4IO_setLEDs(0x0000FFF7); // SET : Interrupts enabled XIntc_Enable(&instIntrCtrl, XPAR_MICROBLAZE_0_AXI_INTC_FIT_TIMER_0_INTERRUPT_INTR); NX4IO_setLEDs(0x0000FFF6); // SET : RGB LED duty cycles and disable output NX4IO_RGBLED_setDutyCycle(RGB1, 64, 0, 64); NX4IO_RGBLED_setChnlEn(RGB1, false, false, false); NX4IO_setLEDs(0x0000FFF5); return XST_SUCCESS; }