// STM32F100 and SI4032 RTTY transmitter // released under GPL v.2 by anonymous developer // enjoy and have a nice day // ver 1.5a #include #include #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 */