diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..35410cac
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/editor.xml b/.idea/editor.xml
new file mode 100644
index 00000000..7b63cd04
--- /dev/null
+++ b/.idea/editor.xml
@@ -0,0 +1,588 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..53624c9e
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 2893ef52..f72a5403 100644
--- a/Makefile
+++ b/Makefile
@@ -9,40 +9,40 @@ ENABLE_SWD ?= 1
ENABLE_OVERLAY ?= 0
ENABLE_LTO ?= 1
-# ---- STOCK QUANSHENG FERATURES ----
+# ---- STOCK QUANSHENG FERATURfvzES ----
ENABLE_UART ?= 1
ENABLE_AIRCOPY ?= 0
ENABLE_FMRADIO = 0
ENABLE_NOAA ?= 0
ENABLE_VOICE ?= 0
-ENABLE_VOX ?= 1
+ENABLE_VOX ?= 0
ENABLE_ALARM ?= 0
ENABLE_TX1750 ?= 0
ENABLE_PWRON_PASSWORD ?= 0
ENABLE_DTMF_CALLING ?= 1
-ENABLE_FLASHLIGHT ?= 1
+ENABLE_FLASHLIGHT ?= 0
ENABLE_BOOTLOADER ?= 0
# ---- CUSTOM MODS ----
ENABLE_BIG_FREQ ?= 1
-ENABLE_KEEP_MEM_NAME ?= 1
-ENABLE_WIDE_RX ?= 1
+ENABLE_KEEP_MEM_NAME ?= 0
+ENABLE_WIDE_RX ?= 0
ENABLE_TX_WHEN_AM ?= 0
ENABLE_F_CAL_MENU ?= 0
ENABLE_CTCSS_TAIL_PHASE_SHIFT ?= 0
ENABLE_BOOT_BEEPS ?= 0
ENABLE_SHOW_CHARGE_LEVEL ?= 0
ENABLE_REVERSE_BAT_SYMBOL ?= 0
-ENABLE_NO_CODE_SCAN_TIMEOUT ?= 1
-ENABLE_AM_FIX ?= 1
-ENABLE_SQUELCH_MORE_SENSITIVE ?= 1
-ENABLE_FASTER_CHANNEL_SCAN ?= 1
-ENABLE_RSSI_BAR ?= 1
-ENABLE_COPY_CHAN_TO_VFO ?= 1
+ENABLE_NO_CODE_SCAN_TIMEOUT ?= 0
+ENABLE_AM_FIX ?= 0
+ENABLE_SQUELCH_MORE_SENSITIVE ?= 0
+ENABLE_FASTER_CHANNEL_SCAN ?= 0
+ENABLE_RSSI_BAR ?= 0
+ENABLE_COPY_CHAN_TO_VFO ?= 0
ENABLE_SPECTRUM = 0
ENABLE_REDUCE_LOW_MID_TX_POWER?= 0
ENABLE_BYP_RAW_DEMODULATORS ?= 0
ENABLE_BLMIN_TMP_OFF ?= 0
-ENABLE_SCAN_RANGES ?= 1
+ENABLE_SCAN_RANGES ?= 0
ENABLE_MDC1200 = 0
ENABLE_MDC1200_SHOW_OP_ARG = 0
ENABLE_MDC1200_SIDE_BEEP = 0
@@ -54,8 +54,8 @@ ENABLE_EEPROM_TYPE = 0
ENABLE_CHINESE_FULL = 0
ENABLE_ENGLISH =0
ENABLE_DOCK ?= 0
-ENABLE_CUSTOM_SIDEFUNCTIONS ?= 1
-ENABLE_SIDEFUNCTIONS_SEND ?= 1
+ENABLE_CUSTOM_SIDEFUNCTIONS ?= 0
+ENABLE_SIDEFUNCTIONS_SEND ?= 0
ENABLE_BLOCK ?= 0
ENABLE_PINYIN =0
ENABLE_TURN ?=1
@@ -64,7 +64,7 @@ ENABLE_AM_FIX_SHOW_DATA ?= 0
ENABLE_AGC_SHOW_DATA ?= 0
ENABLE_TIMER ?= 0
-ENABLE_WARNING ?= 1
+ENABLE_WARNING ?= 0
ENABLE_MESSENGER = 0
ENABLE_MESSENGER_DELIVERY_NOTIFICATION = 0
ENABLE_MESSENGER_NOTIFICATION = 0
@@ -72,6 +72,7 @@ ENABLE_4732 =0
ENABLE_4732SSB =0
ENABLE_DOPPLER =0
+ENABLE_TLE = 1
#############################################################
PACKED_FILE_SUFFIX = LOSEHU132
ifeq ($(ENABLE_PINYIN),1)
@@ -166,7 +167,15 @@ endif
ifeq ($(ENABLE_DOPPLER),1)
OBJS += driver/rtc.o
endif
+ifeq ($(ENABLE_TLE),1)
+ OBJS += tle/eci.o
+ OBJS += tle/sgp.o
+ OBJS += tle/vec.o
+ OBJS += tle/tle.o
+ OBJS += tle/astrotime.o
+ OBJS += tle/util.o
+endif
ifeq ($(ENABLE_MDC1200),1)
OBJS += app/mdc1200.o
endif
@@ -288,7 +297,7 @@ AS = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
ifeq ($(ENABLE_CLANG),0)
- CC = arm-none-eabi-gcc
+ CC =arm-none-eabi-gcc
# Use GCC's linker to avoid undefined symbol errors
# LD += arm-none-eabi-gcc
else
@@ -298,7 +307,7 @@ else
# LD = ld.lld
endif
-OBJCOPY = arm-none-eabi-objcopy
+OBJCOPY =arm-none-eabi-objcopy
SIZE = arm-none-eabi-size
AUTHOR_STRING ?= LOSEHU
@@ -345,7 +354,7 @@ endif
#CFLAGS += -Wpadded
# catch any and all warnings
-CFLAGS += -Wextra
+CFLAGS += -Wextra -fno-strict-aliasing
#CFLAGS += -Wpedantic
# 设置PACKED_FILE_SUFFIX,根据ENABLE_CHINESE_FULL的值设置不同的后缀
@@ -397,6 +406,10 @@ endif
ifeq ($(ENABLE_DOPPLER),1)
CFLAGS += -DENABLE_DOPPLER
endif
+ifeq ($(ENABLE_TLE),1)
+ CFLAGS += -DENABLE_TLE
+
+endif
ifeq ($(ENABLE_4732),1)
CFLAGS += -DENABLE_4732
endif
@@ -596,12 +609,7 @@ endif
full:
$(RM) *.bin
- $(MAKE) build ENABLE_CHINESE_FULL=0 ENABLE_ENGLISH=1 ENABLE_FMRADIO=1 ENABLE_MESSENGER=1 ENABLE_MESSENGER_DELIVERY_NOTIFICATION=1 ENABLE_MESSENGER_NOTIFICATION=1 ENABLE_SPECTRUM=1 ENABLE_MDC1200=1 ENABLE_MDC1200_EDIT=1 ENABLE_MDC1200_CONTACT=1
- $(MAKE) build ENABLE_CHINESE_FULL=4 ENABLE_ENGLISH=1 ENABLE_DOPPLER=1 ENABLE_SPECTRUM=1 ENABLE_FMRADIO=1 ENABLE_MDC1200=1 ENABLE_MDC1200_EDIT=1 ENABLE_MDC1200_CONTACT=1
- $(MAKE) build ENABLE_CHINESE_FULL=0 ENABLE_SPECTRUM=1 ENABLE_FMRADIO=1 ENABLE_MDC1200=1 ENABLE_MDC1200_EDIT=1 ENABLE_MDC1200_CONTACT=1
- $(MAKE) build ENABLE_CHINESE_FULL=4 ENABLE_DOPPLER=1 ENABLE_SPECTRUM=1 ENABLE_FMRADIO=1 ENABLE_MDC1200=1 ENABLE_MDC1200_EDIT=1 ENABLE_MDC1200_CONTACT=1
- $(MAKE) build ENABLE_CHINESE_FULL=4 ENABLE_DOPPLER=1 ENABLE_PINYIN=1 ENABLE_SPECTRUM=1 ENABLE_FMRADIO=1
- $(MAKE) build ENABLE_CHINESE_FULL=4 ENABLE_PINYIN=1 ENABLE_4732=1 ENABLE_4732SSB=1 ENABLE_SPECTRUM=1
+ $(MAKE) build ENABLE_CHINESE_FULL=4 ENABLE_DOPPLER=0 ENABLE_PINYIN=0 ENABLE_SPECTRUM=0 ENABLE_FMRADIO=0
test:
$(RM) *.bin
@@ -640,15 +648,18 @@ flash:
version.o: .FORCE
$(TARGET): $(OBJS)
- @$(LD) $(LDFLAGS) $^ -o $@ $(LIBS)
+ @$(LD) $(LDFLAGS) $^ -o $@ $(LIBS) -lc -g -lm
+
bsp/dp32g030/%.h: hardware/dp32g030/%.def
%.o: %.c | $(BSP_HEADERS)
- @$(CC) $(CFLAGS) $(INC) -c $< -o $@
+ @$(CC) $(CFLAGS) $(INC) -c $< -o $@ -lc -g -lm
+
%.o: %.S
- @$(AS) $(ASFLAGS) $< -o $@
+ @$(AS) $(ASFLAGS) $< -o $@ -lc -g -lm
+
.FORCE:
diff --git a/app/spectrum.c b/app/spectrum.c
index b0ef09a1..1cf6bce3 100644
--- a/app/spectrum.c
+++ b/app/spectrum.c
@@ -1077,9 +1077,9 @@ static void OnKeyDownFreqInput(uint8_t key) {
{
- time[3]=tempFreq/100000;
- time[4]=(tempFreq/1000)%100;
- time[5]=(tempFreq/10)%100;
+ my_time[3]=tempFreq/100000;
+ my_time[4]=(tempFreq/1000)%100;
+ my_time[5]=(tempFreq/10)%100;
RTC_Set();
SetState(previousState);
@@ -1278,7 +1278,7 @@ static void Draw_DOPPLER_Process(uint8_t DATA_LINE) {
else
gFrameBuffer[6][i + 80] = 0b00100010;
}
- sprintf(String, "20%02d-%02d-%02d %02d:%02d:%02d", time[0], time[1], time[2], time[3], time[4], time[5]);
+ sprintf(String, "20%02d-%02d-%02d %02d:%02d:%02d", my_time[0], my_time[1], my_time[2], my_time[3], my_time[4], my_time[5]);
GUI_DisplaySmallest(String, 1, DATA_LINE + 23, false, true);
}
@@ -1530,7 +1530,7 @@ static void Tick() {
if (gNextTimeslice_500ms) {
gNextTimeslice_500ms = false;
- // if a lot of steps then it takes long time
+ // if a lot of steps then it takes long my_time
// we don't want to wait for whole scan
// listening has it's own timer
if(GetStepsCount()>128 && !isListening) {
@@ -1660,7 +1660,7 @@ void RTCHandler(void) {
RTC_Get();
- int32_t NOW_UNIX_TIME = UNIX_TIME(time);
+ int32_t NOW_UNIX_TIME = UNIX_TIME(my_time);
time_diff = satellite.START_TIME_UNIX - NOW_UNIX_TIME; //卫星开始时间-现在时间
time_diff1 = satellite.sum_time + time_diff;//结束-开始+开始-现在
diff --git a/board.c b/board.c
index 8329d870..0c0abdc3 100644
--- a/board.c
+++ b/board.c
@@ -466,9 +466,7 @@ void BOARD_Init(void) {
BACKLIGHT_InitHardware();
BOARD_ADC_Init();
ST7565_Init();
-#ifdef ENABLE_FMRADIO
- BK1080_Init(0, false);
-#endif
+
#if defined(ENABLE_UART) || defined(ENABLED_AIRCOPY)
CRC_Init();
@@ -477,11 +475,11 @@ void BOARD_Init(void) {
}
void write_to_memory(uint32_t address, uint32_t data) {
- // ֵַתΪָ
+ // ����ַ��ֵת��Ϊָ��
uint32_t *target_address = (uint32_t *) address;
- // Ŀַд
+ // ��Ŀ���ַд������
*target_address = data;
- // Ϊ˱Żȷ벻ᱻŻ
+ // Ϊ�˱����Ż���ȷ�����벻�ᱻ�Ż���
volatile uint32_t read_back = *target_address;
}
//JUMP_TO_FLASH(0xa10A,0x20003ff0);
diff --git a/bsp/dp32g030/rtc.h b/bsp/dp32g030/rtc.h
index 9975d54d..656a0045 100644
--- a/bsp/dp32g030/rtc.h
+++ b/bsp/dp32g030/rtc.h
@@ -39,6 +39,6 @@ void RTC_INIT(void);
void RTC_Set( );
void RTC_Get();
-extern uint8_t time[6];
+extern uint8_t my_time[6];
#endif
\ No newline at end of file
diff --git a/compile-with-docker.bat b/compile-with-docker.bat
index f9ef2742..5887156e 100644
--- a/compile-with-docker.bat
+++ b/compile-with-docker.bat
@@ -1,5 +1,4 @@
@echo on
-make clean
docker build -t uvk5 .
docker run --rm -v %CD%\compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app &&rm -rf compiled&& make clean && make full&& cp *.bin compiled-firmware/"
pause
diff --git a/del_linux.sh b/del_linux.sh
index 09e59bde..bd163a6d 100644
--- a/del_linux.sh
+++ b/del_linux.sh
@@ -1,4 +1,4 @@
#!/bin/bash
target_directory="./"
-find "$target_directory" -type f \( -name "*.o" -o -name "*.d" \) -delete
+find "$target_directory" -type f \( -name "*.o" -o -name "*.d" \)
echo "Deletion complete."
diff --git a/driver/rtc.c b/driver/rtc.c
index 63946b81..2a2ef8b4 100644
--- a/driver/rtc.c
+++ b/driver/rtc.c
@@ -7,7 +7,7 @@
#include "driver/system.h"
#include "ui/helper.h"
-uint8_t time[6];
+uint8_t my_time[6];
void RTC_INIT() {
@@ -19,7 +19,7 @@ void RTC_INIT() {
| (0 << 24);//PRE_PERIOD=8s
- EEPROM_ReadBuffer(0X2BC0, time, 6);
+ EEPROM_ReadBuffer(0X2BC0, my_time, 6);
RTC_Set();
diff --git a/main.c b/main.c
index bb34b348..31a9a0a5 100644
--- a/main.c
+++ b/main.c
@@ -13,7 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#include
+#include
+#include
+#include
+#include
+#include
+#include "tle/eci.h"
#include "bsp/dp32g030/gpio.h"
#include "driver/gpio.h"
#include "app/si.h"
@@ -39,9 +45,8 @@
#include "app/uart.h"
#include "string.h"
#include "app/messenger.h"
-
+#include "time.h"
#ifdef ENABLE_DOPPLER
-
#include "app/doppler.h"
#endif
@@ -94,7 +99,12 @@
#include "ui/menu.h"
#include "driver/eeprom.h"
#include "driver/st7565.h"
-
+#include
+#include
+#include
+#include
+#include
+#include "tle/eci.h"
void _putchar(__attribute__((unused)) char c) {
#ifdef ENABLE_UART
@@ -105,9 +115,8 @@ void _putchar(__attribute__((unused)) char c) {
void Main(void) {
- //BOOT_Mode_t BootMode;
- // Enable clock gating of blocks we need
+
SYSCON_DEV_CLK_GATE = 0
| SYSCON_DEV_CLK_GATE_GPIOA_BITS_ENABLE
| SYSCON_DEV_CLK_GATE_GPIOB_BITS_ENABLE
@@ -117,197 +126,85 @@ void Main(void) {
| SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE
| SYSCON_DEV_CLK_GATE_CRC_BITS_ENABLE
| SYSCON_DEV_CLK_GATE_AES_BITS_ENABLE
- | SYSCON_DEV_CLK_GATE_PWM_PLUS0_BITS_ENABLE
- // | (1 << 12)
-#ifdef ENABLE_DOPPLER
-
- | (1 << 22)
-#endif
- ;
-
+ | SYSCON_DEV_CLK_GATE_PWM_PLUS0_BITS_ENABLE;
SYSTICK_Init();
-
BOARD_Init();
-
-
-
-#ifdef ENABLE_UART
UART_Init();
-#endif
-
-
- memset(gDTMF_String, '-', sizeof(gDTMF_String));
- gDTMF_String[sizeof(gDTMF_String) - 1] = 0;
-
- BK4819_Init();
-
-
- BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent);
-
-
- SETTINGS_InitEEPROM();
-
-
- SETTINGS_LoadCalibration();
-#ifdef ENABLE_MESSENGER
- MSG_Init();
-#endif
-#ifdef ENABLE_MDC1200
- MDC1200_init();
-#endif
-// char name[10]="START6789";
-// EEPROM_WriteBuffer(0x02BA0,name,10);
-#ifdef ENABLE_DOPPLER
-
- RTC_INIT();
- INIT_DOPPLER_DATA();
-#endif
-
- RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD);
- RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD);
-
-
- RADIO_SelectVfos();
-
- RADIO_SetupRegisters(true);
-
- for (uint32_t i = 0; i < ARRAY_SIZE(gBatteryVoltages); i++) {
- BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[i], &gBatteryCurrent);
- }
- BATTERY_GetReadings(false);
-#ifdef ENABLE_AM_FIX
- AM_fix_init();
-#endif
-
-#if ENABLE_CHINESE_FULL == 0
- gMenuListCount = 52;
-#else
- gMenuListCount = 53;
-#endif
- gKeyReading0 = KEY_INVALID;
- gKeyReading1 = KEY_INVALID;
- gDebounceCounter = 0;
-//#ifdef ENABLE_4732
-//
-//
-// memset(gStatusLine, 0, sizeof(gStatusLine));
-// UI_DisplayClear();
-// ST7565_BlitStatusLine(); // blank status line
-// ST7565_BlitFullScreen();
-//SI4732_Main();
-//#endif
-#ifdef ENABLE_TIMER
-
-
- BOARD_PORTCON_Init();
- BOARD_GPIO_Init();
- ST7565_Init();
- TIM0_INIT();
memset(gStatusLine, 0, sizeof(gStatusLine));
- UI_DisplayClear();
- ST7565_BlitStatusLine(); // blank status line
+ memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
+ ST7565_BlitStatusLine();
ST7565_BlitFullScreen();
- char str[20]={0}; // 分配一个足够大的字符串数组来存储转换后的字符串
- while(1)
- {
- char str[6];
- show_uint32(TIM0_CNT,0);
- show_uint32(TIMERBASE0_LOW_CNT,1);
- show_uint32(TIMERBASE0_HIGH_CNT,2);
- show_uint32(TIMERBASE0_IF,3);
- show_uint32(TIMERBASE0_IE,4);
- }
-#endif
- UI_DisplayWelcome();
-
-#ifdef ENABLE_BOOTLOADER
-
-
- if(KEYBOARD_Poll() == KEY_MENU)
-{
- for (int i = 0; i < 10*1024; i += 4) {
- uint32_t c;
- EEPROM_ReadBuffer(0x41000 + i, (uint8_t *) &c, 4);
- write_to_memory(0x20001000 + i, c);
- }
- JUMP_TO_FLASH(0x2000110a, 0x20003ff0);
-}
-#endif
- boot_counter_10ms = 250;
- while (boot_counter_10ms > 0 || (KEYBOARD_Poll() != KEY_INVALID)) {
- if (KEYBOARD_Poll() == KEY_EXIT
-#if ENABLE_CHINESE_FULL == 4
- || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE
-#endif
- ) { // halt boot beeps
- boot_counter_10ms = 0;
- break;
- }
-#ifdef ENABLE_BOOT_BEEPS
-
- if ((boot_counter_10ms % 25) == 0)
- AUDIO_PlayBeep(BEEP_880HZ_40MS_OPTIONAL);
-#endif
-
- }
+ GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT);
+ UI_PrintStringSmall("Boot OK", 0, 127, 2);
+ UI_PrintStringSmall("Release Key", 0, 127, 6);
+ ST7565_BlitStatusLine();
+ ST7565_BlitFullScreen();
-#ifdef ENABLE_PWRON_PASSWORD
- if (gEeprom.POWER_ON_PASSWORD < 1000000)
- {
- bIsInLockScreen = true;
- UI_DisplayLock();
- bIsInLockScreen = false;
- }
-#endif
-
- // BOOT_ProcessMode();
- GUI_SelectNextDisplay(DISPLAY_MAIN);
-
- GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0);
-
- gUpdateStatus = true;
-
-#ifdef ENABLE_VOICE
- {
- uint8_t Channel;
-
- AUDIO_SetVoiceID(0, VOICE_ID_WELCOME);
-
- Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO];
- if (IS_MR_CHANNEL(Channel))
- {
- AUDIO_SetVoiceID(1, VOICE_ID_CHANNEL_MODE);
- AUDIO_SetDigitVoice(2, Channel + 1);
- }
- else if (IS_FREQ_CHANNEL(Channel))
- AUDIO_SetVoiceID(1, VOICE_ID_FREQUENCY_MODE);
-
- AUDIO_PlaySingleVoice(0);
- }
-#endif
-
-#ifdef ENABLE_NOAA
- RADIO_ConfigureNOAA();
-#endif
+ const char *line0 = "ISS (ZARYA)";
+ const char *line1 = "1 25544U 98067A 25026.23381182 .00024447 00000+0 42619-3 0 9998";
+ const char *line2 = "2 25544 51.6395 290.1622 0002159 133.7357 10.9595 15.50580823493146";
+ // 解析TLE数据
+tle_data data; // 直接在栈上创建一个tle_data
+ struct tm utc ;
+ utc.tm_isdst=0;
+ utc.tm_yday=26;
+ utc.tm_wday=1;
+ utc.tm_year=125;
+ utc.tm_mon =0;
+ utc.tm_mday=27;
+ utc.tm_hour=8;
+ utc.tm_min=28;
+ utc.tm_sec=42;
+ memset(gFrameBuffer,0,sizeof(gFrameBuffer));
+ ST7565_BlitFullScreen();
+ show_uint32(456,3) ;
+ SYSTEM_DelayMs(3000);
while (1) {
- APP_Update();
+//125 0 27 7 39 3Look: 57.454126 -18.469256
+//Pos: 51.546400, 125.533706
+//
+//125 0 27 7 39 4Look: 57.403762 -18.499665
+//Pos: 51.553088, 125.632517
+//
+//125 0 27 7 39 5Look: 57.353492 -18.530080
+//Pos: 51.559686, 125.731359
- if (gNextTimeslice) {
- APP_TimeSlice10ms();
- }
+ if (tle_parse(line0, line1, line2, &data) == 0) { // 修改为传递指针
+ } else {
+ lat_lon observer = { 50, 50, 50 }; // 设定观察者的经纬度和海拔
- if (gNextTimeslice_500ms) {
- APP_TimeSlice500ms();
- }
+ jd target = to_jd(utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec);
+ look_result look = eci_to_look(&data, observer, target);
+int line=0;
+ memset(gFrameBuffer[line],0,256);
+ char str[20] = {0};
+ sprintf(str, "%d.%d", (int)(look.azimuth), (int)(look.azimuth*100)%100);
+ UI_PrintStringSmall(str, 0, 127, line);
+ sprintf(str, "%d.%d", (int)(look.altitude), (int)(-look.altitude*100)%100);
+ UI_PrintStringSmall(str, 1, 127, line);
+ ST7565_BlitFullScreen();
+ SYSTEM_DelayMs(1000);
+ utc.tm_sec+=1;
+ if(utc.tm_sec >= 60) {
+ utc.tm_sec=0;
+ utc.tm_min+=1;
+
+ }
+ if(utc.tm_min >= 60) {
+ utc.tm_min=0;
+ utc.tm_hour+=1;
+ }
+ }
}
}
+
diff --git a/tle/astrotime.c b/tle/astrotime.c
new file mode 100644
index 00000000..d4f32800
--- /dev/null
+++ b/tle/astrotime.c
@@ -0,0 +1,35 @@
+#include "astrotime.h"
+#include "util.h"
+
+jd jd_year_begin(int year) {
+ year -= 1;
+ long a = year / 100;
+ long b = 2 - a + (a / 4);
+ return (long) (365.25 * year) + (long) (30.6001 * 14) + 1720994.5 + b;
+}
+
+jd to_jd(int year, int month, int day, int hour, int minute, int second) {
+ double jd_start_day = jd_year_begin(year);
+
+ static const int day_accum[2][13] = {
+ {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+ {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
+ };
+ int leap = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
+ int jd_day = day_accum[leap][month] + day;
+
+ static const int seconds_per_day = 24 * 3600;
+ int total_offset_seconds = hour * 3600 + minute * 60 + second;
+ double jd_off = (double) total_offset_seconds / seconds_per_day;
+
+ return jd_start_day + jd_day + jd_off;
+}
+
+gmst to_gmst(jd jd) {
+ double time = frac(jd + 0.5);
+ jd = jd - time;
+ double rel_date = (jd - 2451545.0) / 36525;
+ double gmst = 24110.54841 + rel_date * (8640184.812866 + rel_date * (0.093104 - rel_date * 6.2E-6));
+ gmst = fmod(gmst + 86400.0 * 1.00273790934 * time, 86400.0);
+ return 2 * M_PI * gmst / 86400.0;
+}
diff --git a/tle/astrotime.h b/tle/astrotime.h
new file mode 100644
index 00000000..dfb1df64
--- /dev/null
+++ b/tle/astrotime.h
@@ -0,0 +1,45 @@
+#ifndef FATE_ASTROTIME_H
+#define FATE_ASTROTIME_H
+
+/**
+ * Julian Date represented as a double value
+ */
+typedef double jd;
+
+/**
+ * GMST represented as a radian measure in a double
+ */
+typedef double gmst;
+
+/**
+ * Obtains the Julian Date at the beginning of the given
+ * year.
+ *
+ * @param year the year which to find the julian date
+ */
+jd jd_year_begin(int year);
+
+/**
+ * Converts the given Gregorian time measurements (i.e.
+ * standard calendar measurements) into Julian Days.
+ *
+ * @param year the year which to convert
+ * @param month the month
+ * @param day the day
+ * @param hour the hour in UTC
+ * @param minute the minute in UTC
+ * @param second the second in UTC
+ * @return the Julian Date
+ */
+jd to_jd(int year, int month, int day, int hour, int minute, int second);
+
+/**
+ * Converts the given Julian Date into GMST.
+ *
+ * @param jd the Julian Date
+ * @return the GMST time, in radians
+ */
+gmst to_gmst(jd jd);
+#include
+
+#endif /* FATE_ASTROTIME_H */
diff --git a/tle/eci.c b/tle/eci.c
new file mode 100644
index 00000000..bd1df3a1
--- /dev/null
+++ b/tle/eci.c
@@ -0,0 +1,117 @@
+#include
+#include "eci.h"
+#include "vec.h"
+#include "sgp.h"
+#include "util.h"
+
+const double f = 0.003352810665;
+const double esq = 0.006694379991;
+const double a = 6378.137;
+
+vec lat_lon_to_eci(double lat, gmst theta,double h) {
+ double C = 1 / sqrt(1 + f * (f - 2) * square(sin(lat)));
+ double S = square(1 - f) * C;
+ double r = a * C + h / 1000.0; // 调整半径,考虑高度
+
+ double x = r * cos(lat) * cos(theta);
+ double y = r * cos(lat) * sin(theta);
+ double z = (a * S + h / 1000.0) * sin(lat);
+
+ vec result = {x, y, z};
+ return result;
+}
+
+int tle_to_eci(sgp_result *result, tle_data *tle, jd time) {
+ // Convert TLE epoch into jd so we can figure out the
+ // minutes elapsed since the epoch until the target
+ // time
+ long epoch_yr;
+ if (strl(tle->epoch_yr, &epoch_yr) == 0) {
+ return 0;
+ }
+ static const int current_millenium = 2000;
+ double tle_jd = jd_year_begin(current_millenium + epoch_yr) + tle->epoch_day;
+ double minute_diff = (time - tle_jd) * 1440;
+ if (minute_diff < 0) {
+ return 0;
+ }
+
+ *result = sgp4(tle, minute_diff);
+ return 1;
+}
+
+double clamp(double lat, double max) {
+ double deg = to_degrees(lat);
+ if (deg > max) {
+ return -(max * 2 - deg);
+ }
+
+ if (deg < -max) {
+ return deg + (max * 2);
+ }
+
+ return deg;
+}
+
+look_result eci_to_look(tle_data *tle, lat_lon observer, jd time) {
+ double lat = to_radians(observer.lat);
+ double lon = to_radians(observer.lon);
+ gmst gmst = to_gmst(time);
+ double theta = fmod(gmst + lon, 2 * M_PI);
+
+ vec observer_eci = lat_lon_to_eci(lat, theta,observer.height);
+ sgp_result sgp_eci;
+ if (tle_to_eci(&sgp_eci, tle, time) == 0) {
+ look_result fail = { 0 };
+ return fail;
+ }
+
+ double rx = sgp_eci.r.x - observer_eci.x;
+ double ry = sgp_eci.r.y - observer_eci.y;
+ double rz = sgp_eci.r.z - observer_eci.z;
+ double top_s = sin(lat) * cos(theta) * rx
+ + sin(lat) * sin(theta) * ry
+ - cos(lat) * rz;
+ double top_e = -sin(theta) * rx + cos(theta) * ry;
+ double top_z = cos(lat) * cos(theta) * rx
+ + cos(lat) * sin(theta) * ry
+ + sin(lat) * rz;
+ double az = atan(-top_e / top_s);
+ if (top_s > 0) {
+ az = az + M_PI;
+ }
+ if (az < 0) {
+ az = az + 2 * M_PI;
+ }
+ double rg = sqrt(rx * rx + ry * ry + rz * rz);
+ double el = asin(top_z / rg);
+
+ look_result result = {to_degrees(az), to_degrees(el), rg};
+ return result;
+}
+
+lat_lon eci_to_lat_lon(tle_data *tle, gmst time) {
+ gmst gmst = to_gmst(time);
+ double theta = fmod(gmst, 2 * M_PI);
+
+ sgp_result sgp_eci;
+ if (tle_to_eci(&sgp_eci, tle, time) == 0) {
+ lat_lon fail = { 0 };
+ return fail;
+ }
+
+ double r = sqrt(square(sgp_eci.r.x) + square(sgp_eci.r.y));
+ int rounds = 10;
+ double dphi;
+ double phi = atan2(sgp_eci.r.z, r);
+ do {
+ double phi_i = phi;
+ double C = 1 / sqrt(1 - esq * square(sin(phi_i)));
+ phi = atan2(sgp_eci.r.z + a * C * esq * sin(phi_i), r);
+ dphi = fabs(phi - phi_i);
+ } while (dphi > 1E-6 && --rounds > 0);
+ double lon = atan2(sgp_eci.r.y, sgp_eci.r.x) - theta;
+
+ lat_lon result = { clamp(phi, 90), clamp(lon, 180) };
+ return result;
+}
diff --git a/tle/eci.h b/tle/eci.h
new file mode 100644
index 00000000..b37bb8e4
--- /dev/null
+++ b/tle/eci.h
@@ -0,0 +1,58 @@
+#ifndef FATE_ECI_H
+#define FATE_ECI_H
+
+#include "tle.h"
+#include "astrotime.h"
+#include
+
+/**
+ * Represents the result of calculating the look position
+ * for an observer to a satellite, where azimuth is the
+ * clockwise rotation from true north and the altitude is
+ * the degrees inclination above the observation plane.
+ * Units are in degrees.
+ */
+typedef struct {
+ double azimuth;
+ double altitude;
+ double range;
+} look_result;
+
+/**
+ * Represents a location on the Earth with latitude and
+ * longitude coordinates. Positive north and east. Units
+ * are in degrees.
+ */
+typedef struct {
+ double lat;
+ double lon;
+ double height;
+} lat_lon;
+
+/**
+ * Calculates the look position of the satellite from its
+ * SGP data, the observer position, and the time.
+ *
+ * @param tle the TLE data that will be used
+ * @param observer the observer location on the Earth
+ * @param time the time which to determine the look
+ * location
+ * @return the look location expressed as an azimuth and
+ * altitude
+ */
+look_result eci_to_look(tle_data *tle, lat_lon observer, gmst time);
+
+/**
+ * Calculates the sub-point (i.e. the point below the
+ * satellite formed by a line from the satellite
+ * intersecting at a right angle with a line tangent to the
+ * surface of the Earth) from the given SGP data and time.
+ *
+ * @param tle the TLE data that will be used
+ * @param time the time which to calculate the satellite
+ * position on the Earth
+ * @return a set of latitude and longitude coordinates
+ */
+lat_lon eci_to_lat_lon(tle_data *tle, gmst time);
+
+#endif /* FATE_ECI_H */
diff --git a/tle/sgp.c b/tle/sgp.c
new file mode 100644
index 00000000..3fd3098f
--- /dev/null
+++ b/tle/sgp.c
@@ -0,0 +1,207 @@
+#include
+#include "sgp.h"
+#include "util.h"
+#include "vec.h"
+
+static const double SDP_THRESH_FREQ = 1440.0 / 225.0;
+static const double XKMPER = 6378.135;
+static const double ONE_HALF = 1.0 / 2.0;
+static const double THREE_HALVES = 3.0 / 2.0;
+static const double TWO_THIRDS = 2.0 / 3.0;
+
+static const double a_E = 1.0;
+static const double Q_0 = 1.88027916E-9;
+
+static const double k_e = 0.0743669161;
+static const double k_2 = 5.413080E-4;
+static const double k_4 = 0.62098875E-6;
+static const double S = 1.0122292801892716;
+static const double A_3_COMMA_0 = 2.53881E-06;
+
+sgp_result sgp4(tle_data *data, double minutes_since_epoch) {
+ if (data->rev_per_day < SDP_THRESH_FREQ) {
+ sgp_result fail = { {0}, {0}, {0}, {0} };
+ return fail;
+ }
+
+ double i_0 = to_radians(data->inclination);
+ double OMEGA_0 = to_radians(data->r_node_ascension);
+ double M_0 = to_radians(data->mean_anomaly);
+ double omega_0 = to_radians(data->perigee_arg);
+ double xno = data->rev_per_day * 2 * M_PI / 1440.0;
+ double delta_multiplier = ((3 * square(cos(i_0)) - 1) /
+ pow(1 - square(data->eccentricity), THREE_HALVES));
+
+ double a_1 = pow(k_e / xno, TWO_THIRDS);
+ double delta_1 = THREE_HALVES * (k_2 / square(a_1)) * delta_multiplier;
+ double a_0 = a_1 * (1 - ((1.0 / 3.0) * delta_1) - square(delta_1) - ((134.0 / 81.0) * cube(delta_1)));
+ double delta_0 = THREE_HALVES * (k_2 / square(a_0)) * delta_multiplier;
+ double d_d_n_0 = xno / (1 + delta_0); /* original mean motion */
+ double d_d_a_0 = a_0 / (1 - delta_0); /* semimajor axis */
+
+ unsigned int simple = 0;
+ if ((d_d_a_0 * (1.0 - data->eccentricity) / a_E) < (220.0 / XKMPER + a_E)) {
+ simple = 1;
+ }
+
+ double perigee = (d_d_a_0 * (1 - data->eccentricity) - a_E) * XKMPER;
+ double s = S;
+ double q_0_minus_s_pow_4 = Q_0;
+ if (perigee >= 98 && perigee <= 156) {
+ s = (d_d_a_0 * (1 - data->eccentricity)) - S + a_E; /* s_star */
+ q_0_minus_s_pow_4 = pow(Q_0 - s, 4.0);
+ } else if (perigee < 98) {
+ s = 20.0 / XKMPER + a_E; /* s_star */
+ q_0_minus_s_pow_4 = pow(Q_0 - s, 4.0);
+ }
+
+ double theta = cos(i_0);
+ double xi = 1 / (d_d_a_0 - s);
+ double beta_0 = sqrt(1 - square(data->eccentricity));
+ double eta = d_d_a_0 * data->eccentricity * xi;
+ double C_2 =
+ q_0_minus_s_pow_4 * pow(xi, 4.0) * d_d_n_0 * pow(1 - square(eta), -7.0 / 2.0) *
+ (d_d_a_0 * (1 + THREE_HALVES * square(eta) + 4 * data->eccentricity * eta + data->eccentricity * cube(eta)) +
+ (THREE_HALVES * ((k_2 * xi) / (1 - square(eta)))) *
+ (-ONE_HALF + THREE_HALVES * square(theta)) *
+ (8 + 24 * square(eta) + 3 * pow(eta, 4.0)));
+ double C_1 = data->drag * C_2;
+ double C_3 = (q_0_minus_s_pow_4 * pow(xi, 5.0) * A_3_COMMA_0 * d_d_n_0 * a_E * sin(i_0)) /
+ (k_2 / data->eccentricity);
+ double C_4 = 2 * d_d_n_0 * q_0_minus_s_pow_4 * pow(xi, 4.0) * d_d_a_0 * square(beta_0) * pow(1 - square(eta), -7.0 / 2.0) *
+ ((2 * eta * (1 + data->eccentricity * eta) + ONE_HALF * data->eccentricity + ONE_HALF * cube(eta)) -
+ ((2 * k_2 * xi) / (d_d_a_0 * (1 - square(eta)))) *
+ (
+ 3 * (1 - 3 * square(theta)) *
+ (1 + THREE_HALVES * square(eta) - 2 * data->eccentricity * eta - ONE_HALF * data->eccentricity * cube(eta)) +
+ (3.0 / 4.0) * (1 - square(theta)) * (2 * square(eta) - data->eccentricity * eta - data->eccentricity * cube(eta)) * cos(2 * omega_0))
+ );
+ double C_5 = 2 * q_0_minus_s_pow_4 * pow(xi, 4.0) * d_d_a_0 * square(beta_0) *
+ pow(1 - square(eta), -7.0 / 2.0) *
+ (1 + (11.0 / 4.0) * eta * (eta + data->eccentricity) + data->eccentricity * cube(eta));
+
+ double M_DF = M_0 +
+ (1 + ((3 * k_2 * (-1 + 3 * square(theta))) / (2 * square(d_d_a_0) * cube(beta_0))) +
+ ((3 * square(k_2) * (13 - 78 * square(theta) + 137 * pow(theta, 4.0))) /
+ (16 * pow(d_d_a_0, 4.0) * pow(beta_0, 7.0)))) *
+ d_d_n_0 * minutes_since_epoch;
+ double omega_DF = omega_0 +
+ (-((3 * k_2 * (1 - 5 * square(theta))) / (2 * square(d_d_a_0) * pow(beta_0, 4.0))) +
+ ((3 * square(k_2) * (7 - 114 * square(theta) + 395 * pow(theta, 4.0))) /
+ (16 * pow(d_d_a_0, 4.0) * pow(beta_0, 8.0))) +
+ ((5 * k_4 * (3 - 36 * square(theta) + 49 * pow(theta, 4.0))) /
+ (4.0 * pow(d_d_a_0, 4.0) * pow(beta_0, 8.0)))) *
+ d_d_n_0 * minutes_since_epoch;
+ double OMEGA_DF = OMEGA_0 +
+ ((-(3 * k_2 * theta) / (square(d_d_a_0) * pow(beta_0, 4.0))) +
+ ((3 * square(k_2) * (4 * theta - 19 * cube(theta))) /
+ (2 * pow(d_d_a_0, 4.0) * pow(beta_0, 8.0))) +
+ ((5 * k_4 * theta * (3 - 7 * square(theta))) / (2 * pow(d_d_a_0, 4.0) * pow(beta_0, 8.0)))) *
+ d_d_n_0 * minutes_since_epoch;
+ double delta_omega = data->drag * C_3 * cos(omega_0) * minutes_since_epoch;
+ double delta_M = -TWO_THIRDS * q_0_minus_s_pow_4 * data->drag * pow(xi, 4.0) *
+ (a_E / (data->eccentricity * eta)) *
+ (pow(1 + eta * cos(M_DF), 3.0) - pow(1 + eta * cos(M_0), 3.0));
+ double M_p = M_DF;
+ double omega = omega_DF;
+ double OMEGA = OMEGA_DF -
+ (21.0 / 2.0) * ((d_d_n_0 * k_2 * theta) / (square(d_d_a_0) * square(beta_0))) *
+ C_1 * square(minutes_since_epoch);
+
+ double e;
+ double a;
+ double L;
+ if (simple == 0) {
+ M_p += delta_omega + delta_M;
+ omega -= delta_omega - delta_M;
+ e = data->eccentricity - data->drag * C_4 * minutes_since_epoch -
+ data->drag * C_5 * (sin(M_p) - sin(M_0));
+
+ double D_2 = 4 * d_d_a_0 * xi * square(C_1);
+ double D_3 = (4.0 / 3.0) * d_d_a_0 * square(xi) * (17 * d_d_a_0 + s) * cube(C_1);
+ double D_4 = TWO_THIRDS * d_d_a_0 * cube(xi) * (221 * d_d_a_0 + 31 * s) * pow(C_1, 4.0);
+ a = d_d_a_0 *
+ square(1 - C_1 * minutes_since_epoch -
+ D_2 * square(minutes_since_epoch) -
+ D_3 * cube(minutes_since_epoch) -
+ D_4 * pow(minutes_since_epoch, 4.0));
+ L = M_p + omega + OMEGA + d_d_n_0 * (THREE_HALVES * C_1 * square(minutes_since_epoch) +
+ (D_2 + 2 * square(C_1)) * cube(minutes_since_epoch) +
+ (1.0 / 4.0) * (3 * D_3 + 12 * C_1 * D_2 + 10 * cube(C_1) * pow(minutes_since_epoch, 4.0)) +
+ ((1.0 / 5.0) *
+ (3 * D_4 + 12 * C_1 * D_3 + 6 * square(D_2) + 30 * square(C_1) * D_2 +
+ 15 * pow(C_1, 4.0) * pow(minutes_since_epoch, 5.0))));
+ } else {
+ e = data->eccentricity - data->drag * C_4 * minutes_since_epoch;
+ a = d_d_a_0 * square(1 - C_1 * minutes_since_epoch);
+ L = M_p + omega + OMEGA + d_d_n_0 * (THREE_HALVES * C_1 * square(minutes_since_epoch));
+ }
+ double beta = sqrt(1 - square(e));
+ double n = k_e / sqrt(cube(a));
+
+ double a_xN = e * cos(omega);
+ double L_L = ((A_3_COMMA_0 * sin(i_0)) / (8 * k_2 * a * square(beta))) *
+ (e * cos(omega)) * ((3 + 5 * theta) / (1 + theta));
+ double a_yNL = (A_3_COMMA_0 * sin(i_0)) / (4 * k_2 * a * square(beta));
+ double L_T = L + L_L;
+ double a_yN = e * sin(omega) + a_yNL;
+
+ double AXN_SIN;
+ double AYN_COS;
+ double AXN_COS;
+ double AYN_SIN;
+ double U = fmod(L_T - OMEGA, 2 * M_PI);
+ double E_w_i = U;
+ for (int i = 1; i <= 10; ++i) {
+ double sinpw = sin(E_w_i);
+ double cospw = cos(E_w_i);
+
+ AXN_SIN = a_xN * sinpw;
+ AYN_COS = a_yN * cospw;
+ AXN_COS = a_xN * cospw;
+ AYN_SIN = a_yN * sinpw;
+
+ double dE_w_i = (U - AYN_COS + AXN_SIN - E_w_i) /
+ (-AYN_SIN - AXN_COS + 1) + E_w_i;
+ if (fabs(dE_w_i - E_w_i) <= 1.0E-6) {
+ break;
+ }
+
+ E_w_i = dE_w_i;
+ }
+
+ double e_cos_E = AXN_COS + AYN_SIN;
+ double e_sin_E = AXN_SIN - AYN_COS;
+ double e_L = sqrt(square(a_xN) + square(a_yN));
+ double p_L = a * (1 - square(e_L));
+ double r = a * (1 - e_cos_E);
+ double r_dot = k_e * (sqrt(a) / r) * e_sin_E;
+ double r_f_dot = k_e * (sqrt(p_L) / r);
+ double cos_u = (a / r) * (cos(E_w_i) - a_xN + ((a_yN * e_sin_E) / (1 + sqrt(1 - square(e_L)))));
+ double sin_u = (a / r) * (sin(E_w_i) - a_yN - ((a_xN * e_sin_E) / (1 + sqrt(1 - square(e_L)))));
+ double u = atan2(sin_u, cos_u);
+ double dr = (k_2 / (2 * p_L)) * (1 - square(theta)) * cos(2 * u);
+ double du = (-k_2 / (4 * square(p_L))) * (7 * square(theta) - 1) * sin(2 * u);
+ double dOMEGA = ((3 * k_2 * theta) / (2 * square(p_L))) * sin(2 * u);
+ double di = ((3 * k_2 * theta) / (2 * square(p_L))) * sin(i_0) * cos(2 * u);
+ double dr_dot = (-(k_2 * n) / p_L) * (1 - square(theta)) * sin(2 * u);
+ double dr_f_dot = ((k_2 * n) / p_L) * ((1 - square(theta)) * cos(2 * u) - THREE_HALVES * (1 - 3 * square(theta)));
+ double r_k = r * (1 - THREE_HALVES * k_2 * (sqrt(1 - square(e_L)) / square(p_L)) * (3 * square(theta) - 1)) + dr;
+ double u_k = u + du;
+ double OMEGA_k = OMEGA + dOMEGA;
+ double i_k = i_0 + di;
+ double r_dot_k = r_dot + dr_dot;
+ double r_f_dot_k = r_f_dot + dr_f_dot;
+
+ vec M = {-sin(OMEGA_k) * cos(i_k), cos(OMEGA_k) * cos(i_k), sin(i_k)};
+ vec N = {cos(OMEGA_k), sin(OMEGA_k), 0};
+
+ vec result_U = vec_add(vec_mul(sin(u_k), M), vec_mul(cos(u_k), N));
+ vec result_V = vec_add(vec_mul(cos(u_k), M), vec_mul(-sin(u_k), N));
+
+ vec result_r = vec_mul(XKMPER, vec_mul(r_k, result_U));
+ vec result_r_dot = vec_mul(XKMPER / 60, vec_add(vec_mul(r_dot_k, result_U), vec_mul(r_f_dot_k, result_V)));
+
+ sgp_result result = {result_U, result_V, result_r, result_r_dot};
+ return result;
+}
\ No newline at end of file
diff --git a/tle/sgp.h b/tle/sgp.h
new file mode 100644
index 00000000..5fbf9bd1
--- /dev/null
+++ b/tle/sgp.h
@@ -0,0 +1,18 @@
+#include "tle.h"
+#include "vec.h"
+#include
+
+#ifndef FATE_SGP_H
+#define FATE_SGP_H
+
+typedef struct {
+ vec u; /* orientation */
+ vec v;
+
+ vec r; /* position */
+ vec r_dot; /* velocity */
+} sgp_result;
+
+sgp_result sgp4(tle_data *data, double minutes_since_epoch);
+
+#endif /* FATE_SGP_H */
diff --git a/tle/tle.c b/tle/tle.c
new file mode 100644
index 00000000..0828fa3d
--- /dev/null
+++ b/tle/tle.c
@@ -0,0 +1,358 @@
+#include
+#include
+#include
+#include "tle.h"
+#include "util.h"
+
+/**
+ * Designed to parse space-track.org title lines, they are
+ * prefixed with "0 " so the max len would be 26 and not 24
+ *
+ * @param data the data to fill
+ * @param title the title line
+ * @return 0 if invalid length
+ */
+static int parse_title(tle_data *data, const char *title) {
+ unsigned char len = (unsigned char) strlen(title);
+ if (len > 26) {
+ return 0;
+ }
+
+ /* Cut the beginning "0 " and the newline */
+ len -= 3;
+
+ data->title_len = len;
+ substr(title, 2, len,data->title);
+ if (data->title == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int compute_checksum(const char *str) {
+ int total = 0;
+ for (int i = 0; i < 68; i++) {
+ char c = str[i];
+ if (c == '-') {
+ total += 1;
+ } else if (c >= '0' && c <= '9') {
+ total += c - '0';
+ }
+ }
+
+ return total % 10;
+}
+
+static int parse_line1(tle_data *data, const char *line1) {
+ int checksum = line1[68] - '0';
+ if (compute_checksum(line1) != checksum) {
+ // puts("Checksum failed");
+ return 0;
+ }
+
+ /* sat_num */
+ char sat_num_str[8];
+ substr(line1, 2, 5,sat_num_str);
+
+
+ if (strl(sat_num_str, (long *) &data->sat_num) == 0) {
+ //free(sat_num_str);
+ return 0;
+ }
+
+
+ /* class */
+ data->class = line1[7];
+
+ /* launch_yr */
+ substr(line1, 9, 2,data->launch_yr );
+
+ /* launch_num */
+ char launch_num_str[5] ;
+ substr(line1, 11, 3,launch_num_str);
+
+
+ if (strl(launch_num_str, (long *) &data->launch_num) == 0) {
+ //free(launch_num_str);
+ return 0;
+ }
+
+ //free(launch_num_str);
+
+ /* launch_piece */
+ substr(line1, 14, 3, data->launch_piece );
+ if (data->launch_piece == NULL) {
+ return 0;
+ }
+ data->launch_piece_len = (unsigned char) strlen(data->launch_piece);
+
+ /* epoch_yr */
+ substr(line1, 18, 2,data->epoch_yr);
+ if (data->epoch_yr == NULL) {
+ return 0;
+ }
+
+ /* epoch_day */
+ char epoch_day_str[20];
+ substr(line1, 20, 12,epoch_day_str);
+ if (epoch_day_str == NULL) {
+ return 0;
+ }
+
+ if (strd(epoch_day_str, &data->epoch_day) == 0) {
+ //free(epoch_day_str);
+ return 0;
+ }
+
+ //free(epoch_day_str);
+
+ /* d_mean_motion */
+ char d_mean_motion_str[20];
+ substr(line1, 33, 10,d_mean_motion_str);
+
+ if (strd(d_mean_motion_str, &data->d_mean_motion) == 0) {
+ //free(d_mean_motion_str);
+ return 0;
+ }
+
+ //free(d_mean_motion_str);
+
+ /* dd_mean_motion */
+ double dd_mean_motion_mul = 0;
+ char dd_mean_motion_mul_str[20] ;
+ substr(line1, 44, 6,dd_mean_motion_mul_str);
+ if (dd_mean_motion_mul_str == NULL) {
+ return 0;
+ }
+
+ if (strd(dd_mean_motion_mul_str, &dd_mean_motion_mul) == 0) {
+ //free(dd_mean_motion_mul_str);
+ return 0;
+ }
+
+ //free(dd_mean_motion_mul_str);
+ dd_mean_motion_mul /= 100000;
+
+ int dd_mean_motion_exp = 0;
+ char dd_mean_motion_exp_str[20] ;
+ substr(line1, 50, 2,dd_mean_motion_exp_str);
+ if (dd_mean_motion_exp_str == NULL) {
+ return 0;
+ }
+
+ if (strl(dd_mean_motion_exp_str, (long *) &dd_mean_motion_exp) == 0) {
+ //free(dd_mean_motion_exp_str);
+ return 0;
+ }
+
+ //free(dd_mean_motion_exp_str);
+ data->dd_mean_motion = dd_mean_motion_mul * pow(10, dd_mean_motion_exp);
+
+ /* drag */
+ double drag_mul = 0;
+ char drag_mul_str[20] ; substr(line1, 53, 6,drag_mul_str);
+ if (drag_mul_str == NULL) {
+ return 0;
+ }
+
+ if (strd(drag_mul_str, &drag_mul) == 0) {
+ //free(drag_mul_str);
+ return 0;
+ }
+
+ //free(drag_mul_str);
+ drag_mul /= 100000;
+
+ int drag_exp = 0;
+ char drag_exp_str[20] ; substr(line1, 59, 2,drag_exp_str);
+ if (drag_exp_str == NULL) {
+ return 0;
+ }
+
+ if (strl(drag_exp_str, (long *) &drag_exp) == 0) {
+ //free(drag_exp_str);
+ return 0;
+ }
+
+ //free(drag_exp_str);
+ data->drag = drag_mul * pow(10, drag_exp);
+
+ /* ephemeris */
+ data->ephemeris = (unsigned char) line1[62];
+
+ /* element_num */
+ char element_num_str[20] ;
+ substr(line1, 64, 4,element_num_str);
+ if (element_num_str == NULL) {
+ return 0;
+ }
+
+ if (strl(element_num_str, (long *) &data->element_num) == 0) {
+ //free(element_num_str);
+ return 0;
+ }
+
+ //free(element_num_str);
+
+ return 1;
+}
+
+static int parse_line2(tle_data *data, const char *line2) {
+ int checksum = line2[68] - '0';
+ if (compute_checksum(line2) != checksum) {
+ // puts("Checksum failed");
+ return 0;
+ }
+
+ /* ignore satellite number */
+
+ /* inclination */
+ char inclination_str[20];
+ substr(line2, 8, 8,inclination_str);
+ if (inclination_str == NULL) {
+ return 0;
+ }
+
+ if (strd(inclination_str, &data->inclination) == 0) {
+ //free(inclination_str);
+ return 0;
+ }
+
+ //free(inclination_str);
+
+ /* r_node_ascension */
+ char r_node_ascension_str[20] ;
+ substr(line2, 17, 8,r_node_ascension_str);
+ if (r_node_ascension_str == NULL) {
+ return 0;
+ }
+
+ if (strd(r_node_ascension_str, &data->r_node_ascension) == 0) {
+ //free(r_node_ascension_str);
+ return 0;
+ }
+
+ //free(r_node_ascension_str);
+
+ /* eccentricity */
+ double eccentricity = 0;
+ char eccentricity_str[20] ;
+ substr(line2, 26, 7,eccentricity_str);
+ if (eccentricity_str == NULL) {
+ return 0;
+ }
+
+ if (strd(eccentricity_str, &eccentricity) == 0) {
+ //free(eccentricity_str);
+ return 0;
+ }
+
+ //free(eccentricity_str);
+ data->eccentricity = eccentricity /= 10000000;
+
+ /* perigee_arg */
+ char perigee_arg_str[20] ;
+ substr(line2, 34, 8,perigee_arg_str);
+ if (perigee_arg_str == NULL) {
+ return 0;
+ }
+
+ if (strd(perigee_arg_str, &data->perigee_arg) == 0) {
+ //free(perigee_arg_str);
+ return 0;
+ }
+
+ //free(perigee_arg_str);
+
+ /* mean_anomaly */
+ char mean_anomaly_str[20] ;
+ substr(line2, 43, 8,mean_anomaly_str);
+ if (mean_anomaly_str == NULL) {
+ return 0;
+ }
+
+ if (strd(mean_anomaly_str, &data->mean_anomaly) == 0) {
+ //free(mean_anomaly_str);
+ return 0;
+ }
+
+ //free(mean_anomaly_str);
+
+ /* rev_per_day */
+ char rev_per_day_str[20] ;
+ substr(line2, 52, 11,rev_per_day_str);
+ if (rev_per_day_str == NULL) {
+ return 0;
+ }
+
+ if (strd(rev_per_day_str, &data->rev_per_day) == 0) {
+ //free(rev_per_day_str);
+ return 0;
+ }
+
+ //free(rev_per_day_str);
+
+ /* rev_num */
+ char rev_num_str[20];
+ substr(line2, 63, 5,rev_num_str);
+ if (rev_num_str == NULL) {
+ return 0;
+ }
+
+ if (strl(rev_num_str, (long *) &data->rev_num) == 0) {
+ //free(rev_num_str);
+ return 0;
+ }
+
+ //free(rev_num_str);
+
+ return 1;
+}
+
+int tle_parse(const char *title, const char *line1, const char *line2, tle_data *data) {
+ if (parse_title(data, title) == 0) {
+ return 0; // 解析失败
+ }
+
+ if (parse_line1(data, line1) == 0) {
+ return 0; // 解析失败
+ }
+
+ if (parse_line2(data, line2) == 0) {
+ return 0; // 解析失败
+ }
+
+ return 1; // 成功解析
+}
+
+void tle_print(FILE *stream, tle_data *data) {
+ fprintf(stream, "Title: %s\n", data->title);
+ fprintf(stream, "Satellite Number: %d\n", data->sat_num);
+ fprintf(stream, "Classifier: %c\n", data->class);
+ fprintf(stream, "Launch Year: %s\n", data->launch_yr);
+ fprintf(stream, "Launch Number: %d\n", data->launch_num);
+ fprintf(stream, "Launch Piece: %s\n", data->launch_piece);
+ fprintf(stream, "Epoch Year: %s\n", data->epoch_yr);
+ fprintf(stream, "Epoch Day: %f\n", data->epoch_day);
+ fprintf(stream, "Derivative of Mean Motion / 2: %f\n", data->d_mean_motion);
+ fprintf(stream, "2nd Derivative of Mean Motion / 6: %f\n", data->dd_mean_motion);
+ fprintf(stream, "B* Drag Term: %f\n", data->drag);
+ fprintf(stream, "Ephemeris Type: %c\n", data->ephemeris);
+ fprintf(stream, "Element Number: %d\n", data->element_num);
+ fprintf(stream, "Inclination: %f\n", data->inclination);
+ fprintf(stream, "Right Node Ascension: %f\n", data->r_node_ascension);
+ fprintf(stream, "Eccentricity: %f\n", data->eccentricity);
+ fprintf(stream, "Argument of Perigee: %f\n", data->perigee_arg);
+ fprintf(stream, "Mean Anomaly: %f\n", data->mean_anomaly);
+ fprintf(stream, "Revolutions Per Day: %f\n", data->rev_per_day);
+ fprintf(stream, "Revolutions: %d\n", data->rev_num);
+}
+
+void tle_free(tle_data *data) {
+ //free(data->title);
+ //free(data->launch_yr);
+ //free(data->launch_piece);
+ //free(data->epoch_yr);
+ //free(data);
+}
\ No newline at end of file
diff --git a/tle/tle.h b/tle/tle.h
new file mode 100644
index 00000000..d4f282d7
--- /dev/null
+++ b/tle/tle.h
@@ -0,0 +1,75 @@
+#ifndef FATE_TLE_H
+#define FATE_TLE_H
+
+#include
+
+/**
+ * A year represented as a 2-digit number
+ */
+typedef char *year;
+
+typedef struct {
+ /* TITLE LINE */
+ char title[20];
+ unsigned char title_len;
+
+ /* LINE 1 */
+
+ int sat_num;
+ char class;
+
+ char launch_yr[40];
+ short launch_num;
+ char launch_piece[20];
+ unsigned char launch_piece_len;
+
+ char epoch_yr[40];
+ double epoch_day;
+
+ double d_mean_motion; /* n_0_dot / 2 */
+ double dd_mean_motion; /* n_0_dot_dot / 6 */
+
+ double drag;
+
+ unsigned char ephemeris;
+ short element_num;
+ /* checksum */
+
+ /* LINE 2 */
+
+ double inclination; /* i_0 */
+ double r_node_ascension; /* omega_0 */
+ double eccentricity; /* e_0 */
+ double perigee_arg; /* omega_0 */
+ double mean_anomaly; /* M_0 */
+ double rev_per_day; /* n_0 */
+ int rev_num;
+ /* checksum */
+} tle_data;
+
+/**
+ * Parses and TLE-formatted data using the 3 line format
+ * that includes the title line.
+ *
+ * @param title the title
+ * @param line1 the first line
+ * @param line2 the second line
+ * @return the TLE parsed data, or NULL on failure
+ */
+int tle_parse(const char *title, const char *line1, const char *line2, tle_data *data) ;
+/**
+ * Prints the given TLE data to the given stream.
+ *
+ * @param data the data to print
+ */
+void tle_print(FILE *stream, tle_data *data);
+
+/**
+ * Relinquishes memory allocated to hold the tle_data
+ * struct.
+ *
+ * @param data the data struct to free
+ */
+void tle_free(tle_data *data);
+
+#endif /* FATE_TLE_H */
diff --git a/tle/util.c b/tle/util.c
new file mode 100644
index 00000000..a47d955c
--- /dev/null
+++ b/tle/util.c
@@ -0,0 +1,84 @@
+#include
+#include
+#include
+
+char substr(const char *str, int start, int len, char *buf) {
+
+
+ // 复制子串到缓冲区
+ memcpy(buf, str + start, len);
+ buf[len] = '\0'; // 添加字符串结束符
+
+}
+
+int strl(const char *str, long *value) {
+ char *end_ptr = NULL;
+ long result = strtol(str, &end_ptr, 10);
+ if (result == 0 && str == end_ptr) {
+ return 0;
+ }
+
+ *value = result;
+ return 1;
+}
+
+
+int strd(const char *str, double *value) {
+ if (!str || !value) {
+ return 0; // 输入无效
+ }
+
+ double result = 0.0;
+ bool is_negative = false;
+ bool is_fraction = false;
+ double fraction_divisor = 1.0;
+
+ // 跳过前导空格
+ while (*str == ' ') {
+ str++;
+ }
+
+ // 处理正负号
+ if (*str == '-') {
+ is_negative = true;
+ str++;
+ } else if (*str == '+') {
+ str++;
+ }
+
+ // 检查第一个字符是否是数字或小数点
+ if ((*str < '0' || *str > '9') && *str != '.') {
+ return 0; // 非法输入
+ }
+
+ // 处理数字部分
+ while ((*str >= '0' && *str <= '9') || *str == '.') {
+ if (*str == '.') {
+ if (is_fraction) {
+ return 0; // 多个小数点,非法输入
+ }
+ is_fraction = true;
+ } else {
+ if (is_fraction) {
+ fraction_divisor *= 10.0;
+ result += (*str - '0') / fraction_divisor;
+ } else {
+ result = result * 10.0 + (*str - '0');
+ }
+ }
+ str++;
+ }
+
+ // 处理负号
+ if (is_negative) {
+ result = -result;
+ }
+
+ // 检查是否还有多余字符
+ if (*str != '\0') {
+ return 0; // 非法输入
+ }
+
+ *value = result;
+ return 1; // 成功解析
+}
diff --git a/tle/util.h b/tle/util.h
new file mode 100644
index 00000000..fa86426f
--- /dev/null
+++ b/tle/util.h
@@ -0,0 +1,92 @@
+#ifndef FATE_UTIL_H
+#define FATE_UTIL_H
+#define M_PI 3.14159265358979323846
+#include
+#include
+#include
+
+/**
+ * Multiplies the given number by itself.
+ *
+ * CONSTRAINT: x <= 1.34E154
+ */
+static inline double square(double x) {
+ return x * x;
+}
+
+/**
+ * Multiplies the given number times itself 3 times.
+ *
+ * CONSTRAINT: x <= 5.64E102
+ */
+static inline double cube(double x) {
+ return x * x * x;
+}
+
+/**
+ * Obtains the fractional portion of a double value.
+ *
+ * @param x the value which to obtain the fraction
+ * @return the fractional portion
+ */
+static inline double frac(double x) {
+ return x - (long) x;
+}
+
+/**
+ * Converts the given number to radians.
+ *
+ * CONSTRAINT: x is in degrees
+ * CONSTRAINT: x <= 1.14E306
+ */
+static inline double to_radians(double x) {
+ static const double MULTIPLIER = M_PI / 180;
+
+ return x * MULTIPLIER;
+}
+
+/**
+ * Converts the given number to degrees.
+ *
+ * CONSTRAINT: x is in radians
+ * CONSTRAINT: x <= 9.98E305
+ */
+static inline double to_degrees(double x) {
+ static const double MULTIPLIER = 180 / M_PI;
+
+ return x * MULTIPLIER;
+}
+
+/**
+ * Takes the substring of the given string, starting from
+ * start and ending len characters later.
+ *
+ * CONSTRAINT: start >= 0
+ * CONSTRAINT: start + len <= strlen(str)
+ *
+ * @param str the string to obtain the substring
+ * @param start the beginning index, inclusive
+ * @param len the number of characters to copy
+ * @return the new substring, or NULL on failure
+ */
+char substr(const char *str, int start, int len, char *buf);
+
+/**
+ * Converts a given string into a long value.
+ *
+ * @param str the string to convert
+ * @param value the pointer at which to store the result
+ * @return 0 on failure
+ */
+int strl(const char *str, long *value);
+
+/**
+ * Converts a given string into a double value.
+ *
+ * @param str the string to convert
+ * @param value the pointer at which to store the result
+ * @return 0 on failure
+ */
+int strd(const char *str, double *value);
+
+#endif /* FATE_UTIL_H */
diff --git a/tle/vec.c b/tle/vec.c
new file mode 100644
index 00000000..2f666901
--- /dev/null
+++ b/tle/vec.c
@@ -0,0 +1,16 @@
+#include
+#include "vec.h"
+
+vec vec_mul(double scalar, vec vector) {
+ vec result = {vector.x * scalar, vector.y * scalar, vector.z * scalar};
+ return result;
+}
+
+vec vec_add(vec vector1, vec vector2) {
+ vec result = {vector1.x + vector2.x, vector1.y + vector2.y, vector1.z + vector2.z};
+ return result;
+}
+
+void vec_print(FILE *stream, vec vector) {
+ fprintf(stream, "{ %f, %f, %f }\n", vector.x, vector.y, vector.z);
+}
diff --git a/tle/vec.h b/tle/vec.h
new file mode 100644
index 00000000..fb5bc311
--- /dev/null
+++ b/tle/vec.h
@@ -0,0 +1,32 @@
+#ifndef FATE_VEC_H
+#define FATE_VEC_H
+#include
+
+#include
+
+typedef struct {
+ double x;
+ double y;
+ double z;
+} vec;
+
+/**
+ * Performs a scalar multiplication on the given vector.
+ *
+ * @return a new vector containing the multiplied values
+ */
+vec vec_mul(double, vec);
+
+/**
+ * Adds the values of two vectors together.
+ *
+ * @return a new vector containing the added values
+ */
+vec vec_add(vec, vec);
+
+/**
+ * Prints the given vector to the given stream.
+ */
+void vec_print(FILE *stream, vec);
+
+#endif /* FATE_VEC_H */
diff --git a/ui/main.c b/ui/main.c
index 0dfcfbfd..2d68e9ef 100644
--- a/ui/main.c
+++ b/ui/main.c
@@ -21,7 +21,7 @@
#include "app/dtmf.h"
#include "font.h"
#include "app/chFrScanner.h"
-
+int vfo_num=0;
#ifdef ENABLE_AM_FIX
#include "am_fix.h"
#endif
diff --git a/win_make.bat b/win_make.bat
index 426a9be3..950bd31d 100644
--- a/win_make.bat
+++ b/win_make.bat
@@ -22,9 +22,9 @@
::
:: Temporarily add the compiler and make program directories to the system PATH ..
::
-@set PATH="C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin";%PATH%
-@set PATH="C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\arm-none-eabi\bin";%PATH%
-@set PATH="C:\Program Files (x86)\GnuWin32\bin\";%PATH%
+@set PATH="C:\gcc-arm-none-eabi-10.3-2021.10\bin";%PATH%
+@set PATH="C:\gcc-arm-none-eabi-10.3-2021.10\arm-none-eabi\bin";%PATH%
+@set PATH="D:\Program Files (x86)\GnuWin32\bin\";%PATH%
:: Do the compile
::