// ============================================================================
// Copyright (c) 2022 by Terasic Technologies Inc.
// ============================================================================
//
// Permission:
//
//   Terasic grants permission to use and modify this code for use
//   in synthesis for all Terasic Development Boards and Altera Development
//   Kits made by Terasic.  Other use of this code, including the selling
//   ,duplication, or modification of any portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL/Verilog or C/C++ source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Terasic provides no warranty regarding the use
//   or functionality of this code.
//
// ============================================================================
//
//  Terasic Technologies Inc
//  No.80, Fenggong Rd., Hukou Township, Hsinchu County 303035. Taiwan
//
//
//                     web: http://www.terasic.com/
//                     email: support@terasic.com
//
// ============================================================================

#include "terasic_includes.h"
#include <stdbool.h>

typedef bool (*LP_VERIFY_FUNC)(void);

bool TEST_Board_Info(void);

typedef struct {
    LP_VERIFY_FUNC func;
    char szName[128];
} FUNC_INFO;

FUNC_INFO szFuncList[] = { { TEST_Board_Info, "Display Board Info" } };

void GUI_ShowMenu(void)
{
    int nNum, i;

    nNum = sizeof(szFuncList) / sizeof(szFuncList[0]);
    printf("======= Agilex Demo Program =======\n");
    for (i = 0; i < nNum; i++) {
        printf("[%d] %s\n", i, szFuncList[i].szName);
    }
    printf("Input your chioce:");
}

int GUI_QueryUser(void)
{
    int nChoice = 0;
    scanf("%d", &nChoice);
    printf("%d\n", nChoice);
    return nChoice;
}

//===============================================================
int main(void)
{
    int nChoice;
    int nNum;
    bool bPass;

    nNum = sizeof(szFuncList) / sizeof(szFuncList[0]);
    while (1) {
        GUI_ShowMenu();
        nChoice = GUI_QueryUser();
        if (nChoice >= 0 && nChoice < nNum) {
            bPass = szFuncList[nChoice].func();
            printf("%s Test:%s\n", szFuncList[nChoice].szName,
                   bPass ? "PASS" : "NG");
        }
    }

}

bool TEST_Board_Info(void)
{
    uint16_t power_in_voltage;
    uint16_t core_voltage, vcc1p2_voltage;
    float core_voltage_float, vcc1p2_voltage_float;
    uint16_t core_current, vcc1p2_current;
    float core_current_float, vcc1p2_current_float;
    uint16_t fan_speed;
    uint16_t temperature_fpga, temperature_board1, temperature_board2,temperature_power;
    //uint16_t pin_status;

    power_in_voltage = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_POWER_IN_VOLTAGE_BASE) & 0xFFFF;
    core_voltage = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_CORE_VOLTAGE_BASE) & 0xFFFF;
    core_current = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_CORE_CURRENT_BASE) & 0xFFFF;
    vcc1p2_voltage = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_VCC1P2_VOLTAGE_BASE) & 0xFFFF;
    vcc1p2_current = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_VCC1P2_CURRENT_BASE) & 0xFFFF;
    fan_speed = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_FAN_SPEED_BASE) & 0xFFFF;
    temperature_fpga = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_TEMPERATURE_FPGA_BASE) & 0xFFFF;
    temperature_board1 = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_TEMPERATURE_BOARD1_BASE) & 0xFFFF;
    temperature_board2 = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_TEMPERATURE_BOARD2_BASE) & 0xFFFF;
    temperature_power = IORD_ALTERA_AVALON_PIO_DATA(BOARD_INFO_TEMPERATURE_POWER_BASE) & 0xFFFF;

    core_voltage_float = core_voltage / 1000.0; //unit : mV
    core_current_float = core_current / 100.0; //unit : 10mA

    vcc1p2_voltage_float = vcc1p2_voltage / 1000.0; //unit : mV
    vcc1p2_current_float = vcc1p2_current / 100.0; //unit : 10mA

    printf("==== Temperature ====\n");
    printf("\tFPGA: %d*C\n", temperature_fpga);
    printf("\tBoard 1: %d*C\n", temperature_board1);
    printf("\tBoard 2: %d*C\n", temperature_board2);
    printf("\Power: %d*C\n", temperature_power);
    printf("\n");
    printf("==== Fan ====\n");
    printf("\tFan RPM: %d\n", fan_speed);
    printf("\n");
    printf("==== Power (12V) Monitor ====\n");
    printf("\tVoltage       = %.3f V \n", power_in_voltage / 1000.0);
    printf("==== Core Power Monitor ====\n");
    printf("\tVoltage       = %.3f V \n", core_voltage_float);
    printf("\tCurrent       = %.3f A \n", core_current_float);
    printf("\tPower         = %.3f W \n", core_voltage_float * core_current_float);
    printf("==== VCC1P2 Power Monitor ====\n");
    printf("\tVoltage       = %.3f V \n", vcc1p2_voltage_float);
    printf("\tCurrent       = %.3f A \n", vcc1p2_current_float);
    printf("\tPower         = %.3f W \n", vcc1p2_voltage_float * vcc1p2_current_float);

    return true;
}
