TEST_F(Helium_100_Live_Radio_Test, GetConfig)
{
    struct he100_settings * settings;
    settings = (struct he100_settings *) malloc (sizeof(struct he100_settings));
    int result = HE100_getConfig(fdin,settings);

    FILE *test_log;
    test_log = Shakespeare::open_log(LOG_PATH,PROCESS);
    HE100_printSettings( test_log, *settings );
    fclose(test_log);

    ASSERT_EQ(CS1_SUCCESS,result);
}
TEST_F(Helium_100_Test, TestCollectValidConfig)
{
    unsigned char config1[CFG_FRAME_LENGTH] = {0x00,0x87,0x01,0x01,0x00,0x00,0xa8,0x3c,0x02,0x00,0x08,0xab,0x06,0x00,0x56,0x41,0x33,0x4f,0x52,0x42,0x56,0x45,0x32,0x43,0x55,0x41,0x05,0x00,0x00,0x00,0x41,0x80,0x00,0x00};
    unsigned char config2[CFG_FRAME_LENGTH] = {0x00,0x00,0x01,0x01,0x00,0x00,0x48,0x33,0x02,0x00,0x98,0x93,0x06,0x00,0x56,0x41,0x33,0x4F,0x52,0x42,0x56,0x45,0x32,0x43,0x55,0x41,0x09,0x00,0x00,0x00,0x43,0x00,0x00,0x00}; 

    struct he100_settings test_settings_1 = HE100_collectConfig(config1);
    struct he100_settings test_settings_2 = HE100_collectConfig(config2);

    int validation_result = 1; 
    validation_result = HE100_validateConfig(test_settings_1);

    FILE *test_log;
    test_log = Shakespeare::open_log(LOG_PATH,PROCESS);
    if (test_log != NULL) {
      HE100_printSettings( test_log, test_settings_1 );
      HE100_printSettings( test_log, test_settings_2 );
      fclose(test_log);
    }

    ASSERT_EQ (0, validation_result);   
    validation_result = HE100_validateConfig(test_settings_2);
    ASSERT_EQ (0, validation_result);   
}
TEST_F(Helium_100_Live_Radio_Test, SetConfig)
{
    unsigned char config[CFG_PAYLOAD_LENGTH] = {0x00,0x00,0x01,0x01,0x00,0x00,0x48,0x33,0x02,0x00,0x98,0x93,0x06,0x00,0x56,0x41,0x33,0x4f,0x52,0x42,0x56,0x45,0x32,0x43,0x55,0x41,0x05,0x00,0x00,0x00,0x41,0x80,0x00,0x00};
    struct he100_settings settings = HE100_collectConfig(config);

    FILE *test_log;
    test_log = Shakespeare::open_log(LOG_PATH,PROCESS);
    HE100_printSettings( test_log, settings );
    fclose(test_log);

    int result = HE100_setConfig(fdin,settings);

    ASSERT_EQ(CS1_SUCCESS,result);
}
TEST_F(Helium_100_Test, PrepareConfig) 
{
    unsigned char config1[CFG_PAYLOAD_LENGTH] = {0x00,0x00,0x01,0x01,0x00,0x00,0xa8,0x3c,0x02,0x00,0x08,0xab,0x06,0x00,0x56,0x41,0x33,0x4f,0x52,0x42,0x56,0x45,0x32,0x43,0x55,0x41,0x00,0x00,0x00,0x00,0x41,0x80,0x00,0x00};

    unsigned char config_result[CFG_PAYLOAD_LENGTH] = {0};
    struct he100_settings test_settings = HE100_collectConfig(config1);
    HE100_printSettings( stdout, test_settings );

    //HE100_swapConfigEndianness(test_settings);

    ASSERT_EQ(
        CS1_SUCCESS,
        HE100_prepareConfig(*config_result, test_settings)
    );
    printf ("Byte: x \t CFG_BYTE_LIST             \t Exp\t :\t Act\n");
    for (z=0; z<CFG_PAYLOAD_LENGTH; z++) {
        printf ("Byte: %d \t %s \t 0x%X\t :\t 0x%X\n",z,CFG_BYTE_LIST[z],config1[z],config_result[z]);
        ASSERT_EQ(
            config1[z],
            config_result[z]
        );
    }
}
/*
 * TestCollectValidConfig_ALL
 * 
 * This test compares both ways of setting the configuration on the radio.
 * 
 * Method 1 - assign the config byte array manually
 * Method 2 - use the configuration structures
 *
 * Both methods are employed to produce config sequences, then they are 
 * compared byte-by-byte for consistency
 */
TEST_F(Helium_100_Test, TestCollectValidConfig_ALL)
{
    // assign callsigns to buffers which will be used later
    char source_callsign[] = "VA3ORB";
    char destination_callsign[] = "VE2CUA";

    /* 
     * Old method - assign each config byte explicitly
     * - Insane
     * - Terrible
     * - Error Prone
     */
    //unsigned char config1a[CFG_FRAME_LENGTH] = {0x00,0x6f,0x01,0x01,0x00,0x00,0x48,0x33,0x02,0x00,0x98,0x93,0x06,0x00,0x56,0x41,0x33,0x4f,0x52,0x42,0x56,0x45,0x32,0x43,0x55,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

    /* 
     * Method 1 - assign the config byte array manually
     * - Must be careful to use macros for assignments
     * - Error Prone
     */
    unsigned char config1a[CFG_FRAME_LENGTH] = {0};
    config1a[CFG_IF_BAUD_BYTE] = CFG_IF_BAUD_9600;
    config1a[CFG_PA_BYTE] = 111;
    config1a[CFG_RF_RX_BAUD_BYTE] = CFG_RF_BAUD_9600;
    config1a[CFG_RF_TX_BAUD_BYTE] = CFG_RF_BAUD_9600;
    config1a[CFG_RX_MOD_BYTE] = CFG_RX_MOD_GFSK;
    config1a[CFG_TX_MOD_BYTE] = CFG_TX_MOD_GFSK;
    // CFG_RX_FREQ_DEFAULT 144200L
    config1a[CFG_RX_FREQ_BYTE1] = 0x48;
    config1a[CFG_RX_FREQ_BYTE2] = 0x33;
    config1a[CFG_RX_FREQ_BYTE3] = 0x02;
    config1a[CFG_RX_FREQ_BYTE4] = 0x00;
    // CFG_TX_FREQ_DEFAULT 431000L
    config1a[CFG_TX_FREQ_BYTE1] = 0x98;
    config1a[CFG_TX_FREQ_BYTE2] = 0x93;
    config1a[CFG_TX_FREQ_BYTE3] = 0x06;
    config1a[CFG_TX_FREQ_BYTE4] = 0x00;

    // need to use memcpy to assign the callsigns
    memcpy (
        config1a+CFG_SRC_CALL_BYTE,
        &source_callsign,
        CFG_CALLSIGN_LEN
    );
    memcpy (
        config1a+CFG_DST_CALL_BYTE,
        &destination_callsign,
        CFG_CALLSIGN_LEN
    );

    config1a[CFG_TX_PREAM_BYTE] = CFG_TX_PREAM_DEF; // zero preamble bytes
    config1a[CFG_TX_PREAM_BYTE] = CFG_TX_PREAM_DEF; // zero preamble bytes
    config1a[CFG_TX_POSTAM_BYTE] = CFG_TX_POSTAM_DEF; // zero postamble bytes  
    config1a[CFG_TX_POSTAM_BYTE] = CFG_TX_POSTAM_DEF; // zero postamble bytes  
    config1a[CFG_FUNCTION_CONFIG_BYTE] = 3; 
    config1a[CFG_FUNCTION_CONFIG_BYTE+1] = 0; // LED ON
    config1a[CFG_FUNCTION_CONFIG2_BYTE] = 0;
    config1a[CFG_FUNCTION_CONFIG2_BYTE+1] = 0;

    /* 
     * Method 2 - use the configuration structures
     * - Must create 
     *   - he100_settings struct
     *   - function_config struct (bitfield)
     *   - function_config2 struct (bitfield)
     */
    struct he100_settings config1b;
    struct function_config fc1;
    fc1.led                       = CFG_FC_LED_RXTOG;
    fc1.pin13                     = CFG_FC_PIN13_OFFLOGICLOW;
    fc1.pin14                     = CFG_FC_PIN14_OFFLOGICLOW;
    fc1.crc_tx                    = CFG_FC_RX_CRC_OFF; 
    fc1.crc_rx                    = CFG_FC_TX_CRC_OFF;
    fc1.telemetry_dump_status     = CFG_FC_TELEMETRY_DUMP_OFF;
    fc1.telemetry_rate            = CFG_FC_TELEMETRY_RATE_P10HZ;
    fc1.telemetry_status          = CFG_FC_TELEMETRY_OFF;
    fc1.beacon_radio_reset_status = CFG_FC_BEACON_CODE_RESET_OFF;
    fc1.beacon_code_upload_status = CFG_FC_BEACON_CODE_UPLOAD_OFF;
    fc1.beacon_oa_cmd_status      = CFG_FC_BEACON_OA_COMMANDS_OFF;
    fc1.beacon_0=0; // LEAVE 0 - factory settings restore flag

    struct function_config2 fc2;
    fc2.t0   = 0;  // leave 0, unknown
    fc2.t4   = 0;  // leave 0, unknown
    fc2.t8   = 0;  // leave 0, unknown
    fc2.tbd  = 0; // leave 0, unknown
    fc2.txcw = CFG_FC_TXCW_OFF;
    fc2.rxcw = CFG_FC_RXCW_OFF;
    fc2.rafc = CFG_FC_RAFC_OFF;

    config1b.interface_baud_rate = CFG_IF_BAUD_9600;
    config1b.tx_power_amp_level = 111;
    config1b.rx_rf_baud_rate = CFG_RF_BAUD_9600;
    config1b.tx_rf_baud_rate = CFG_RF_BAUD_9600;
    config1b.rx_modulation = CFG_RX_MOD_GFSK;
    config1b.tx_modulation = CFG_TX_MOD_GFSK;
    config1b.rx_freq = 144200L; // 0x23348
    config1b.tx_freq = 431000L; // 0x69398 
    
    // still need to use memcpy to assign the callsigns
    memcpy (
        &config1b.source_callsign,
        &source_callsign,
        CFG_CALLSIGN_LEN
    );
    memcpy (
        &config1b.destination_callsign,
        &destination_callsign,
        CFG_CALLSIGN_LEN
    );

    config1b.tx_preamble = CFG_TX_PREAM_DEF;
    config1b.tx_postamble = CFG_TX_POSTAM_DEF;
    config1b.function_config = fc1;
    config1b.function_config2 = fc2;

    HE100_printSettings(stdout, config1b);

    unsigned char config2[CFG_PAYLOAD_LENGTH] = {0};
    ASSERT_EQ(
        CS1_SUCCESS,
        HE100_prepareConfig(*config2, config1b)
    );

    uint16_t fc1_int = (uint16_t)config2[CFG_FUNCTION_CONFIG_BYTE];
    print_binary(fc1_int);
    uint16_t fc2_int = (uint16_t)config2[CFG_FUNCTION_CONFIG2_BYTE];
    print_binary(fc2_int);

    printf ("Byte: x \t CFG_BYTE_LIST             \t Exp\t :\t Act\n");
    // check that config1 is the same as config1a
    for (z=0; z<CFG_PAYLOAD_LENGTH; z++) {
        printf ("Byte: %d \t %s \t 0x%X\t :\t 0x%X\n",z,CFG_BYTE_LIST[z],config1a[z],config2[z]);
        ASSERT_EQ(
            config1a[z],
            config2[z]
        );
    }
}