// STM32F100 and SI4032 RTTY transmitter
// released under GPL v.2 by anonymous developer
// enjoy and have a nice day
// ver 1.5a
#include <stm32f10x_gpio.h>
#include <stm32f10x_usart.h>
#include "f_rtty.h"
#include "config.h"
#include "locator.h"

#define GREEN  GPIO_Pin_7
#define RED  GPIO_Pin_8

/*
int main(void) {
    system_init();
    delay_init();

    init_timer(1000);

    printf("I2C Init\n");

    i2c_init();

    si5351_test();
}
 */
/*
int main_bmp280(void)
{
    //initialise_monitor_handles();
    system_init();
    delay_init();

    //printf("I2C Init\n");

    i2c_init();

    bmp280 bmp280_dev;
    bmp280_dev.port = &DEFAULT_I2C_PORT;
    bmp280_dev.addr = BMP280_I2C_ADDRESS_1;

    bmp280_params_t bmp280_params = {
            .mode = BMP280_MODE_NORMAL,
            .filter = BMP280_FILTER_16,
            .oversampling_pressure = BMP280_ULTRA_HIGH_RES,
            .oversampling_temperature = BMP280_ULTRA_HIGH_RES,
            .oversampling_humidity = BMP280_ULTRA_HIGH_RES,
            .standby = BMP280_STANDBY_250,
    };

    //printf("BMP280 Init\n");
    char *test = "gg11";
    //printf("test1: %s\n", test);
    int test2 = 1234;
    //printf("test2: %d\n", test2);

    bool bmp280_init_success = bmp280_init(&bmp280_dev, &bmp280_params);
    if (bmp280_init_success) {
        //printf("BMP280 Init success\n");
    } else {
        //printf("BMP280 Init failure\n");
    }

    int32_t temperature;
    uint32_t pressure, humidity;

    while (true) {
        GPIO_ResetBits(GPIOB, RED);
        //printf("Measuring...\n");
        bmp280_read_fixed(&bmp280_dev, &temperature, &pressure, &humidity);
        //printf("----\n");
        //printf("Temp: %d\n", temperature);
        //printf("Pressure: %d\n", pressure);
        //printf("Humidity: %d\n", humidity);
        _delay_ms(1000);
        GPIO_SetBits(GPIOB, RED);
        _delay_ms(1000);
    }
}
*/
/*
const unsigned char test = 0; // 0 - normal, 1 - short frame only cunter, height, flag
char callsign[15] = {RTTY_CALLSIGN};
char rtty_comment[25] = {RTTY_COMMENT};

unsigned int send_cun;        //frame counter
char status[2] = {'N'};

//GPSEntry gpsData;
int8_t si4032_temperature;
uint16_t voltage;
volatile int adc_bottom = 2000;

unsigned int led_timeout = 600 * RTTY_SPEED; // Approx. 10 minutes
volatile uint8_t led_enabled = 1; // Flag to disable LEDs after a timeout

volatile char flaga = 0;
uint16_t CRC_rtty = 0x12ab;  //checksum
char buffer[200];
char locator[13];

volatile unsigned char pun = 0;
volatile unsigned int cun = 10;
volatile unsigned char tx_on = 0;
volatile unsigned int tx_on_delay;
volatile unsigned char tx_enable = 0;
rttyStates send_rtty_status = rttyZero;
volatile char *rtty_buf;
volatile uint16_t button_pressed = 0;
volatile uint8_t disable_armed = 0;

void collect_telemetry_data(void);

void send_rtty_packet(void);

uint16_t gps_CRC16_checksum(char *string);

void send_aprs_packet(void);

void send_morse_message(void);
*/

/**
 * GPS data processing
 */
 /*
void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        //ubxg6010_handle_incoming_byte((uint8_t) USART_ReceiveData(USART1));
    } else if (USART_GetITStatus(USART1, USART_IT_ORE) != RESET) {
        USART_ReceiveData(USART1);
    } else {
        USART_ReceiveData(USART1);
    }
}

volatile int ready = 0;
volatile int gen = 1;
volatile int counter = 0;
volatile int tone = 0;
volatile uint16_t freq = 100;
volatile int ledstate = 0;
*/
/*
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);


        if (ready) {
            if (gen) {
                GPIO_ResetBits(GPIOB, radioSDIpin); // Low will TX at carrier + deviation
            } else {
                GPIO_SetBits(GPIOB, radioSDIpin); // High will TX at carrier - deviation
            }
            gen = !gen;

            uint16_t speed = (tone + 1) * 600 * 2;
            counter = (counter + 1) % speed;
            if (counter == 0) {
                tone = (tone + 1) % 4;
                init_timer(speed);
            }
        }

        if (counter == 0) {
            freq += 100;

            //mod_timer_set_freq(freq);
            //radio_set_tx_frequency(434.250 + ((float) freq) / 1000000);

            if (freq >= 5000) {
                freq = 100;
            }

            if (ledstate) {
                GPIO_SetBits(GPIOB, GREEN);
            } else {
                GPIO_ResetBits(GPIOB, GREEN);
            }
            ledstate = !ledstate;
        }

        counter = (counter + 1) % 1000;
*/
        /*    if (aprs_is_active()){
        aprs_timer_handler();
      } else {
        if (ALLOW_DISABLE_BY_BUTTON){
          if (ADCVal[1] > adc_bottom){
            button_pressed++;
            if (button_pressed > (RTTY_SPEED / 3)){
              disable_armed = 1;
              GPIO_SetBits(GPIOB, RED);
              GPIO_SetBits(GPIOB, GREEN);
            }
          } else {
            if (disable_armed){
              GPIO_SetBits(GPIOA, GPIO_Pin_12);
            }
            button_pressed = 0;
          }
          if (button_pressed == 0) {
           adc_bottom = ADCVal[1] * 1.1;	// dynamical reference for power down level
          }
        }
        if (tx_on) {
          send_rtty_status = send_rtty((char *) rtty_buf);
          if (!disable_armed){
            if (send_rtty_status == rttyEnd) {
              if (led_enabled) GPIO_SetBits(GPIOB, RED);
              if (*(++rtty_buf) == 0) {
                tx_on = 0;
                tx_on_delay = TX_DELAY / (1000/RTTY_SPEED);
                tx_enable = 0;
                radio_disable_tx();
              }
            } else if (send_rtty_status == rttyOne) {
              radio_rw_register(0x73, RTTY_DEVIATION, 1);
              if (led_enabled) GPIO_SetBits(GPIOB, RED);
            } else if (send_rtty_status == rttyZero) {
              radio_rw_register(0x73, 0x00, 1);
              if (led_enabled) GPIO_ResetBits(GPIOB, RED);
            }
          }
        }
        if (!tx_on && --tx_on_delay == 0) {
          tx_enable = 1;
          tx_on_delay--;
        }
        if (--cun == 0) {
          if (pun) {
            if (led_enabled) GPIO_ResetBits(GPIOB, GREEN);
            pun = 0;
          } else {
            if (flaga & 0x80) {
              if (led_enabled) GPIO_SetBits(GPIOB, GREEN);
            }
            pun = 1;
          }
          cun = 200;
        }
      }

      if (!LED_ENABLED && led_enabled && !--led_timeout) led_enabled = 0;

    }

}
*/

        /*
void TIM1_BRK_TIM15_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM15, TIM_IT_CC2) != RESET) {
        TIM_ClearITPendingBit(TIM15, TIM_IT_CC2);

        if (ledstate) {
            GPIO_SetBits(GPIOB, GREEN);
        } else {
            GPIO_ResetBits(GPIOB, GREEN);
        }
        ledstate = !ledstate;

    }
}
*/

        /*
int old_main(void)
{
//    initialise_monitor_handles();
#ifdef DEBUG
    debug();
#endif
    system_init();

    init_port();

    init_timer(1000);
    delay_init();
            ubxg6010_init();

    if (led_enabled) GPIO_SetBits(GPIOB, RED);
    // USART_SendData(USART3, 0xc);

    printf("main!\n");

    deinit_usart_debug();
    i2c_init();

    radio_soft_reset();
    // setting RTTY TX frequency
    //radio_set_tx_frequency(434.250);

    // setting TX power
    radio_rw_register(0x6D, 00 | (TX_POWER & 0x0007), 1);

    // initial RTTY modulation
    radio_rw_register(0x71, 0x00, 1);

    // Temperature Value Offset
    radio_rw_register(0x13, 0xF0, 1);

    // Temperature Sensor Calibration
    radio_rw_register(0x12, 0x00, 1);

    // ADC configuration
    radio_rw_register(0x0f, 0x80, 1);
    rtty_buf = buffer;
    tx_on = 0;
    tx_enable = 1;

    uint8_t rtty_before_aprs_left = RTTY_TO_APRS_RATIO;
    uint8_t morse_countdown = RTTY_TO_MORSE_RATIO;

    radio_set_tx_frequency(434.250);

    //_delay_ms(2);
    //_delay_ms(2);

    // The frequency deviation can be calculated: Fd = 625 Hz x fd[8:0].
    // Zero disables deviation between 0/1 bits
    radio_rw_register(0x72, 1, 1);
    // The frequency offset can be calculated as Offset = 156.25 Hz x (hbsel + 1) x fo[7:0]. fo[9:0] is a twos complement value. fo[9] is the sign bit.
    // For 70cm band hbsel is 1, so offset step is 312.5 Hz
    radio_rw_register(0x73, 0, 1);
    radio_rw_register(0x74, 0, 1);
    // Direct Async Mode with OOK modulation
    //radio_rw_register(0x71, 0b00010001, 1);
    // Direct Async Mode with FSK modulation
    radio_rw_register(0x71, 0b00010010, 1);

    //radio_enable_tx();

    spi_deinit();

    // USART interrupts interfere with direct mode transmission
    USART_Cmd(USART1, DISABLE);

    uint16_t mark = 1000000 / 1200 / 2;
    uint16_t space = 1000000 / 2200 / 2;

    uint16_t iter = 0;

    //GPIO_SetBits(GPIOC, radioNSELpin);

    //init_mod_timer(freq);

    // ready = 1;

    // FSK example
    while (1) {
        // NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);
        //__WFI();
        GPIO_SetBits(GPIOB, RED);
        _delay_ms(500);
        GPIO_ResetBits(GPIOB, RED);
        _delay_ms(500);
        //printf("freq: %d\n", freq);
    }

    // FSK example with frequency offset
    while (1) {
        for (int i = 0; i < 1000; i++) {
            spi_init();
            radio_rw_register(0x73, 0, 1);
            spi_deinit();
            GPIO_SetBits(GPIOB, RED);
            GPIO_SetBits(GPIOB, radioSDIpin); // High will TX at carrier - deviation
            _delay_ms(500);
            GPIO_ResetBits(GPIOB, RED);
            GPIO_ResetBits(GPIOB, radioSDIpin); // Low will TX at carrier + deviation
            _delay_ms(500);

            spi_init();
            radio_rw_register(0x73, 1, 1);
            spi_deinit();
            GPIO_SetBits(GPIOB, RED);
            GPIO_SetBits(GPIOB, radioSDIpin); // High will TX at carrier - deviation
            _delay_ms(500);
            GPIO_ResetBits(GPIOB, RED);
            GPIO_ResetBits(GPIOB, radioSDIpin); // High will TX at carrier + deviation
            _delay_ms(500);
        }

        for (int i = 0; i < 1000; i++) {
            //GPIO_SetBits(GPIOB, RED);
            GPIO_SetBits(GPIOB, radioSDIpin);
            _delay_us(250, 0);
            //GPIO_ResetBits(GPIOB, RED);
            GPIO_ResetBits(GPIOB, radioSDIpin);
            _delay_us(250, 0);
        }
    }

    // OOK example
    while (1) {
        GPIO_SetBits(GPIOB, RED);
        GPIO_SetBits(GPIOB, radioSDIpin);
        _delay_ms(500);
        GPIO_ResetBits(GPIOB, RED);
        GPIO_ResetBits(GPIOB, radioSDIpin); // OOK carrier TX is on when SDI is low
        _delay_ms(500);
    }
/*    if (tx_on == 0 && tx_enable) {
      if (rtty_before_aprs_left){
        if (SEND_MORSE && !--morse_countdown) {
          send_morse_message();
          morse_countdown = RTTY_TO_MORSE_RATIO;
        }
        if (SEND_RTTY) send_rtty_packet();
        else _delay_ms(TX_DELAY);
        rtty_before_aprs_left--;
      } else {
        rtty_before_aprs_left = RTTY_TO_APRS_RATIO;
        if (SEND_APRS) send_aprs_packet();
      }

    } else {
        NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);
      __WFI();
    }
  }
}
         */
/*
void collect_telemetry_data(void)
{
    si4032_temperature = radio_read_temperature();
    voltage = ADCVal[0] * 600 / 4096;
    ublox_get_last_data(&gpsData);
    if (gpsData.fix >= 3) flaga |= 0x80;
    else flaga &= ~0x80;
    if (RTTY_WWL || SEND_MORSE_WWL)
        longlat2locator(gpsData.lon_raw, gpsData.lat_raw, locator);
}

void send_rtty_packet(void)
{
    start_bits = RTTY_PRE_START_BITS;
    collect_telemetry_data();
    uint8_t lat_d = (uint8_t) abs(gpsData.lat_raw / 10000000);
    uint32_t lat_fl = (uint32_t) abs(abs(gpsData.lat_raw) - lat_d * 10000000) / 1000;
    uint8_t lon_d = (uint8_t) abs(gpsData.lon_raw / 10000000);
    uint32_t lon_fl = (uint32_t) abs(abs(gpsData.lon_raw) - lon_d * 10000000) / 1000;

    int packetLength = sprintf(buffer, "$$$$%s,%d", callsign, send_cun);
    if (SEND_RTTY_TIME)
        packetLength += sprintf(buffer + packetLength, ",%02u:%02u:%02u", gpsData.hours, gpsData.minutes,
                gpsData.seconds);
    if (SEND_RTTY_LATLON)
        packetLength += sprintf(buffer + packetLength, ",%s%u.%04lu,%s%u.%04lu",
                gpsData.lat_raw < 0 ? "-" : "", lat_d, lat_fl,
                gpsData.lon_raw < 0 ? "-" : "", lon_d, lon_fl);
    if (SEND_RTTY_HEIGHT)
        packetLength += sprintf(buffer + packetLength, ",%ld", (gpsData.alt_raw / 1000));
    if (SEND_RTTY_SPEED)
        packetLength += sprintf(buffer + packetLength, ",%ld", gpsData.speed_raw);
    if (SEND_RTTY_MESSAGE)
        packetLength += sprintf(buffer + packetLength, ",%s", RTTY_WWL ? locator : rtty_comment);
    if (SEND_RTTY_TEMPERATURE)
        packetLength += sprintf(buffer + packetLength, ",%d", si4032_temperature);
    if (SEND_RTTY_VOLTAGE)
        packetLength += sprintf(buffer + packetLength, ",%d.%02d", voltage / 100, voltage - voltage / 100 * 100);
    if (SEND_RTTY_SATELLITES)
        packetLength += sprintf(buffer + packetLength, ",%d", gpsData.sats_raw);
    if (SEND_RTTY_GPSDATA)
        packetLength += sprintf(buffer + packetLength, ",%d,%d,%02x",
                gpsData.ok_packets,
                gpsData.bad_packets,
                flaga);

    CRC_rtty = gps_CRC16_checksum(buffer + 4);
    sprintf(buffer + packetLength, "*%04X\n", CRC_rtty & 0xffff);
    rtty_buf = buffer;
    radio_enable_tx();
    tx_on = 1;

    send_cun++;
}

uint16_t gps_CRC16_checksum(char *string)
{
    uint16_t crc = 0xffff;
    char i;
    while (*(string) != 0) {
        crc = crc ^ (*(string++) << 8);
        for (i = 0; i < 8; i++) {
            if (crc & 0x8000)
                crc = (uint16_t) ((crc << 1) ^ 0x1021);
            else
                crc <<= 1;
        }
    }
    return crc;
}

void send_aprs_packet(void)
{
    radio_enable_tx();
    collect_telemetry_data();
    USART_Cmd(USART1, DISABLE);
    aprs_send_position(gpsData, si4032_temperature, voltage);
    USART_Cmd(USART1, ENABLE);
    radio_disable_tx();
}

void send_morse_message(void)
{
    tx_enable = 0;
    collect_telemetry_data();
    int messageLength = sprintf(buffer, "%s", MORSE_PREFIX);
    if (SEND_MORSE_WWL)
        messageLength += sprintf(buffer + messageLength, " IN %s", locator);
    if (SEND_MORSE_HEIGHT)
        messageLength += sprintf(buffer + messageLength, " ASL %ld", (gpsData.alt_raw / 1000));
    if (SEND_MORSE_VOLTAGE)
        messageLength += sprintf(buffer + messageLength, " BAT %d.%02d", voltage / 100, voltage - voltage / 100 * 100);
    messageLength += sprintf(buffer + messageLength, "%s", MORSE_SUFFIX);

    // Set CW offset
    radio_rw_register(0x73, 1, 1);

    sendMorse(buffer);
    _delay_ms(2000);
    tx_enable = 1;
}

#ifdef  DEBUG
void assert_failed(uint8_t* file, uint32_t line)
{
    while (1);
}
#endif
*/
