00001
00080
00081 #include <18f252.h>
00082 #device ADC=10
00083
00084
00085
00086 #fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
00087
00088
00089 #include <stdlib.h>
00090 #include <string.h>
00091
00092
00093 #use delay(clock=19200000)
00094
00095
00096 #use rs232(baud=57600, xmit=PIN_B7, rcv=PIN_B6, stream=PC_HOST)
00097
00098
00099 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
00100
00101 #use fast_io(A)
00102 #use fast_io(B)
00103 #use fast_io(C)
00104
00105
00106
00107
00108
00110 typedef boolean bool_t;
00111
00113 typedef signed int8 int8_t;
00114
00116 typedef unsigned int8 uint8_t;
00117
00119 typedef signed int16 int16_t;
00120
00122 typedef unsigned int16 uint16_t;
00123
00125 typedef signed int32 int32_t;
00126
00128 typedef unsigned int32 uint32_t;
00129
00130
00131
00132
00133
00134
00136 #define IO_FLASH_CS PIN_A0
00137
00138 #define IO_CUT_DOWN PIN_A1
00139
00140 #define IO_BALLAST_PUMP PIN_A2
00141
00142 #define IO_PS0 PIN_A3
00143 #define IO_UPDATE PIN_A5
00144
00145 #define IO_CS PIN_B0
00146 #define IO_PA PIN_B2
00147 #define IO_GPS_PWR PIN_B3
00148 #define IO_LED PIN_B4
00149
00150 #define IO_PS1 PIN_C0
00151 #define IO_OSK PIN_C2
00152
00153
00154 #bit SPEN = 0xfab.7
00155
00156 bool_t cutDownIsActivate();
00157
00159 typedef enum
00160 {
00162 DDS_MODE_POWERDOWN,
00163
00165 DDS_MODE_APRS,
00166
00168 DDS_MODE_PSK31,
00169
00171 DDS_MODE_HF_APRS
00172 } DDS_MODE;
00173
00174 void ddsInit();
00175 void ddsPhase (bool_t phase);
00176 void ddsSetOutputScale (uint16_t scale);
00177 void ddsSetAmplitude (uint8_t amplitude);
00178 inline void ddsPTT (bool_t state);
00179 void ddsSetFreq (uint32_t freq);
00180 void ddsSetFTW (uint32_t ftw);
00181 void ddsSetMode (DDS_MODE mode);
00182
00183 void flashErase();
00184 uint8_t flashGetByte ();
00185 uint8_t flashReadElectronicSignature();
00186 void flashReadBlock(uint32_t address, uint8_t *block, uint16_t length);
00187 void flashSendByte(uint8_t value);
00188 void flashSendAddress(uint32_t address);
00189 void flashWriteBlock(uint32_t address, uint8_t *block, uint8_t length);
00190 uint8_t flashReadES();
00191
00193 typedef enum
00194 {
00196 GPS_NO_FIX,
00197
00199 GPS_2D_FIX,
00200
00202 GPS_3D_FIX
00203 } GPS_FIX_TYPE;
00204
00206 typedef struct
00207 {
00209 bool_t updateFlag;
00210
00212 uint8_t month;
00213
00215 uint8_t day;
00216
00218 uint8_t hours;
00219
00221 uint8_t minutes;
00222
00224 uint8_t seconds;
00225
00227 uint16_t year;
00228
00230 int32_t latitude;
00231
00233 int32_t longitude;
00234
00236 int32_t altitudeCM;
00237
00239 int32_t altitudeFeet;
00240
00242 uint16_t vSpeed;
00243
00245 uint16_t hSpeed;
00246
00248 uint16_t heading;
00249
00251 uint16_t dop;
00252
00254 uint16_t status;
00255
00257 uint8_t trackedSats;
00258
00260 uint8_t visibleSats;
00261 } GPSPOSITION_STRUCT;
00262
00264 GPSPOSITION_STRUCT gpsPosition;
00265
00266 void gpsInit();
00267 bool_t gpsIsReady();
00268 GPS_FIX_TYPE gpsGetFixType();
00269 int32_t gpsGetPeakAltitude();
00270 void gpsPowerOn();
00271 void gpsPowerOff();
00272 bool_t gpsSetup();
00273 void gpsUpdate();
00274
00275 int16_t lm92GetTemp();
00276
00278 typedef enum
00279 {
00281 LOG_BOOTED = 0xb4,
00282
00284 LOG_COORD = 0xa5,
00285
00287 LOG_TEMPERATURE_1 = 0x96,
00288
00290 LOG_VOLTAGE = 0x87,
00291
00293 LOG_TEMPERATURE_2 = 0x78,
00294
00296 LOG_PUMP = 0x69
00297 } LOG_TYPE;
00298
00299 void logInit();
00300 uint32_t logGetAddress();
00301 void logSetDisableFlag (bool_t disableFlag);
00302 void logType (LOG_TYPE type);
00303 void logUint8 (uint8_t value);
00304 void logInt16 (int16_t value);
00305 void logInt32 (int32_t value);
00306
00307 bool_t psk31CreateDataPacket();
00308 void psk31Init();
00309 void psk31TimeUpdate();
00310 void psk31TxPacket(uint8_t minutes);
00311 void psk31TxByte (uint8_t value);
00312 void psk31TxNull ();
00313 void psk31TxString (char *string, uint8_t length);
00314
00315 bool_t serialHasData();
00316 void serialInit();
00317 uint8_t serialRead();
00318 void serialUpdate();
00319
00320 uint16_t sysCRC16(uint8_t *buffer, uint8_t length, uint16_t crc);
00321 inline void sysPAOutput (bool_t state);
00322
00323
00324 #define TIME_DUTYCYCLE_0 0
00325 #define TIME_DUTYCYCLE_20 2
00326 #define TIME_DUTYCYCLE_70 7
00327
00328
00329 typedef enum
00330 {
00331 TIME_MODE_APRS,
00332 TIME_MODE_PSK31,
00333 TIME_MODE_HF_APRS
00334 } TIME_MODE;
00335
00336 uint8_t timeGetTicks();
00337 void timeInit();
00338 uint8_t timeGetHours();
00339 uint8_t timeGetMinutes();
00340 void timeSetDutyCycle (uint8_t dutyCycle);
00341 void timeSetMode (TIME_MODE mode);
00342 void timeUpdate();
00343
00344
00345 typedef enum
00346 {
00347 TNC_BOOT_MESSAGE,
00348 TNC_STATUS,
00349 TNC_GGA,
00350 TNC_RMC
00351 } TNC_PACKET_TYPE;
00352
00353 void tncInit();
00354 bool_t tncIsFree();
00355 void tncTimeUpdate();
00356 void tncTxByte (uint8_t value);
00357 void tncTxPacket(TNC_PACKET_TYPE tncPacketType);
00358
00367
00368 #define BALLAST_3D_FIX_COUNT 10
00369
00371 #define BALLAST_HOLD_ALTITUDE 30500l
00372
00374 enum BALLAST_MODE
00375 {
00377 WAIT_ACTIVATION,
00378
00380 CONTROL_ALTITUDE,
00381
00383 PUMP_RUN,
00384
00386 PUMP_RUN_DELAY
00387 };
00388
00390 uint16_t ballastPumpCount;
00391
00393 uint8_t ballast3DFixCount;
00394
00396 uint8_t ballastTimeCount;
00397
00399 BALLAST_MODE ballastMode;
00400
00402 bool_t ballastState;
00403
00409 uint16_t ballastGetPumpCount()
00410 {
00411 return ballastPumpCount;
00412 }
00413
00417 void ballastInit()
00418 {
00419 ballastPumpCount = 0;
00420 ballastTimeCount = 0;
00421 ballast3DFixCount = 0;
00422 ballastState = true;
00423 ballastMode = WAIT_ACTIVATION;
00424 }
00425
00431 void ballastSetState (bool_t state)
00432 {
00433 ballastState = state;
00434 }
00435
00441 void ballastLogEvent (bool_t state)
00442 {
00443 logType (LOG_PUMP);
00444 logUint8 ((state ? 0x01 : 0x00));
00445 logUint8 (gpsPosition.hours);
00446 logUint8 (gpsPosition.minutes);
00447 logUint8 (gpsPosition.seconds);
00448 logInt32 (gpsPosition.altitudeCM);
00449 }
00450
00455 void ballastCheck()
00456 {
00457 if (!ballastState)
00458 {
00459 ballast3DFixCount = 0;
00460 return;
00461 }
00462
00463 if (gpsGetFixType() == GPS_3D_FIX)
00464 {
00465 if (ballast3DFixCount < BALLAST_3D_FIX_COUNT)
00466 ++ballast3DFixCount;
00467 } else
00468 ballast3DFixCount = 0;
00469
00470
00471 switch (ballastMode)
00472 {
00473 case WAIT_ACTIVATION:
00474 if (ballast3DFixCount == BALLAST_3D_FIX_COUNT)
00475 if (gpsPosition.altitudeFeet > BALLAST_HOLD_ALTITUDE)
00476 {
00477 ++ballastPumpCount;
00478 ballastMode = CONTROL_ALTITUDE;
00479 }
00480
00481
00482 if (timeGetHours() == 1 && timeGetMinutes() == 30)
00483 {
00484 ++ballastPumpCount;
00485 ballastMode = CONTROL_ALTITUDE;
00486 }
00487
00488 break;
00489
00490 case CONTROL_ALTITUDE:
00491 if (ballast3DFixCount == BALLAST_3D_FIX_COUNT)
00492 if (gpsPosition.altitudeFeet < BALLAST_HOLD_ALTITUDE)
00493 {
00494 output_high (IO_BALLAST_PUMP);
00495
00496 ballastLogEvent (true);
00497
00498 ballastTimeCount = 0;
00499
00500 ballastMode = PUMP_RUN;
00501 }
00502 break;
00503
00504 case PUMP_RUN:
00505 if (++ballastTimeCount == 5)
00506 {
00507 output_low (IO_BALLAST_PUMP);
00508
00509 ballastLogEvent (false);
00510
00511 ++ballastPumpCount;
00512
00513 ballastTimeCount = 0;
00514 ballastMode = PUMP_RUN_DELAY;
00515 }
00516
00517 break;
00518
00519 case PUMP_RUN_DELAY:
00520 if (++ballastTimeCount == 60)
00521 ballastMode = CONTROL_ALTITUDE;
00522 break;
00523 }
00524 }
00525
00536
00537 #define CUTDOWN_3D_FIX_COUNT 10
00538
00540 uint8_t cutDownTimer;
00541
00543 uint8_t cutDown3DFixCount;
00544
00546 bool_t cutDownFlag;
00547
00553 bool_t cutDownIsActivate()
00554 {
00555 return cutDownFlag;
00556 }
00557
00561 void cutDownInit()
00562 {
00563 cutDownFlag = false;
00564 cutDownTimer = 0;
00565 cutDown3DFixCount = 0;
00566 }
00567
00571 void cutDownActivate()
00572 {
00573 output_high (IO_CUT_DOWN);
00574 cutDownTimer = 7;
00575 cutDownFlag = true;
00576 }
00577
00581 void cutDownCheck()
00582 {
00583
00584 if (cutDownTimer != 0)
00585 if (--cutDownTimer == 0)
00586 output_low (IO_CUT_DOWN);
00587
00588
00589 if (cutDownFlag)
00590 return;
00591
00592
00593 if (timeGetHours() == 49)
00594 cutDownActivate();
00595
00596
00597 if (gpsGetFixType() == GPS_3D_FIX)
00598 {
00599 if (cutDown3DFixCount < CUTDOWN_3D_FIX_COUNT)
00600 ++cutDown3DFixCount;
00601 } else
00602 cutDown3DFixCount = 0;
00603
00604
00605 if (cutDown3DFixCount == CUTDOWN_3D_FIX_COUNT)
00606 if (gpsPosition.longitude > -298800000)
00607 cutDownActivate();
00608 }
00609
00620
00621 #define DDS_AD9954_CFR1 0x00
00622
00624 #define DDS_AD9954_CFR2 0x01
00625
00627 #define DDS_AD9954_ASF 0x02
00628
00630 #define DDS_AD9954_ARR 0x03
00631
00633 #define DDS_AD9954_FTW0 0x04
00634
00636 #define DDS_AD9954_FTW1 0x06
00637
00639 #define DDS_AD9954_NLSCW 0x07
00640
00642 #define DDS_AD9954_PLSCW 0x08
00643
00645 #define DDS_AD9954_RWCW0 0x07
00646
00648 #define DDS_AD9954_RWCW1 0x08
00649
00651 #define DDS_RAM 0x0b
00652
00654 #define DDS_FREQ_TO_FTW_DIGITS 9
00655
00657 const uint32_t DDS_MULT[DDS_FREQ_TO_FTW_DIGITS] = { 11, 1, 8, 4, 8, 1, 0, 6, 6 };
00658
00660 const uint32_t DDS_DIVISOR[DDS_FREQ_TO_FTW_DIGITS - 1] = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
00661
00663 const uint16_t DDS_AMP_TO_SCALE[] = { 16383, 15467, 14601, 13785, 13013, 12286, 11598, 10949, 10337, 9759, 9213, 8697,
00664 8211, 7752, 7318, 6909, 6522, 6157, 5813, 5488, 5181, 4891, 4617, 4359, 4115, 3885, 3668, 3463,
00665 3269, 3086, 2913, 2750, 2597, 2451, 2314, 2185, 2062, 1947, 1838, 1735, 1638 };
00666
00667
00668 const uint32_t freqTable[256] =
00669 {
00670 566175115
00671 ,566176488
00672 ,566177860
00673 ,566179229
00674 ,566180597
00675 ,566181961
00676 ,566183321
00677 ,566184676
00678 ,566186026
00679 ,566187368
00680 ,566188704
00681 ,566190031
00682 ,566191349
00683 ,566192658
00684 ,566193956
00685 ,566195242
00686 ,566196517
00687 ,566197778
00688 ,566199026
00689 ,566200260
00690 ,566201478
00691 ,566202680
00692 ,566203866
00693 ,566205035
00694 ,566206185
00695 ,566207317
00696 ,566208429
00697 ,566209522
00698 ,566210593
00699 ,566211644
00700 ,566212672
00701 ,566213677
00702 ,566214660
00703 ,566215618
00704 ,566216552
00705 ,566217462
00706 ,566218345
00707 ,566219203
00708 ,566220034
00709 ,566220838
00710 ,566221615
00711 ,566222363
00712 ,566223083
00713 ,566223774
00714 ,566224436
00715 ,566225068
00716 ,566225670
00717 ,566226242
00718 ,566226783
00719 ,566227292
00720 ,566227770
00721 ,566228217
00722 ,566228631
00723 ,566229014
00724 ,566229364
00725 ,566229681
00726 ,566229965
00727 ,566230216
00728 ,566230434
00729 ,566230619
00730 ,566230770
00731 ,566230888
00732 ,566230972
00733 ,566231023
00734 ,566231040
00735 ,566231023
00736 ,566230972
00737 ,566230888
00738 ,566230770
00739 ,566230619
00740 ,566230434
00741 ,566230216
00742 ,566229965
00743 ,566229681
00744 ,566229364
00745 ,566229014
00746 ,566228631
00747 ,566228217
00748 ,566227770
00749 ,566227292
00750 ,566226783
00751 ,566226242
00752 ,566225670
00753 ,566225068
00754 ,566224436
00755 ,566223774
00756 ,566223083
00757 ,566222363
00758 ,566221615
00759 ,566220838
00760 ,566220034
00761 ,566219203
00762 ,566218345
00763 ,566217462
00764 ,566216552
00765 ,566215618
00766 ,566214660
00767 ,566213677
00768 ,566212672
00769 ,566211644
00770 ,566210593
00771 ,566209522
00772 ,566208429
00773 ,566207317
00774 ,566206185
00775 ,566205035
00776 ,566203866
00777 ,566202680
00778 ,566201478
00779 ,566200260
00780 ,566199026
00781 ,566197778
00782 ,566196517
00783 ,566195242
00784 ,566193956
00785 ,566192658
00786 ,566191349
00787 ,566190031
00788 ,566188704
00789 ,566187368
00790 ,566186026
00791 ,566184676
00792 ,566183321
00793 ,566181961
00794 ,566180597
00795 ,566179229
00796 ,566177860
00797 ,566176488
00798 ,566175115
00799 ,566173743
00800 ,566172371
00801 ,566171001
00802 ,566169634
00803 ,566168270
00804 ,566166910
00805 ,566165555
00806 ,566164205
00807 ,566162862
00808 ,566161527
00809 ,566160200
00810 ,566158882
00811 ,566157573
00812 ,566156275
00813 ,566154989
00814 ,566153714
00815 ,566152453
00816 ,566151205
00817 ,566149971
00818 ,566148753
00819 ,566147551
00820 ,566146365
00821 ,566145196
00822 ,566144046
00823 ,566142914
00824 ,566141802
00825 ,566140709
00826 ,566139638
00827 ,566138587
00828 ,566137559
00829 ,566136554
00830 ,566135571
00831 ,566134613
00832 ,566133678
00833 ,566132769
00834 ,566131886
00835 ,566131028
00836 ,566130197
00837 ,566129393
00838 ,566128616
00839 ,566127868
00840 ,566127148
00841 ,566126457
00842 ,566125795
00843 ,566125163
00844 ,566124561
00845 ,566123989
00846 ,566123448
00847 ,566122939
00848 ,566122460
00849 ,566122014
00850 ,566121599
00851 ,566121217
00852 ,566120867
00853 ,566120550
00854 ,566120266
00855 ,566120015
00856 ,566119797
00857 ,566119612
00858 ,566119461
00859 ,566119343
00860 ,566119259
00861 ,566119208
00862 ,566119191
00863 ,566119208
00864 ,566119259
00865 ,566119343
00866 ,566119461
00867 ,566119612
00868 ,566119797
00869 ,566120015
00870 ,566120266
00871 ,566120550
00872 ,566120867
00873 ,566121217
00874 ,566121599
00875 ,566122014
00876 ,566122460
00877 ,566122939
00878 ,566123448
00879 ,566123989
00880 ,566124561
00881 ,566125163
00882 ,566125795
00883 ,566126457
00884 ,566127148
00885 ,566127868
00886 ,566128616
00887 ,566129393
00888 ,566130197
00889 ,566131028
00890 ,566131886
00891 ,566132769
00892 ,566133678
00893 ,566134613
00894 ,566135571
00895 ,566136554
00896 ,566137559
00897 ,566138587
00898 ,566139638
00899 ,566140709
00900 ,566141802
00901 ,566142914
00902 ,566144046
00903 ,566145196
00904 ,566146365
00905 ,566147551
00906 ,566148753
00907 ,566149971
00908 ,566151205
00909 ,566152453
00910 ,566153714
00911 ,566154989
00912 ,566156275
00913 ,566157573
00914 ,566158882
00915 ,566160200
00916 ,566161527
00917 ,566162862
00918 ,566164205
00919 ,566165555
00920 ,566166910
00921 ,566168270
00922 ,566169634
00923 ,566171001
00924 ,566172371
00925 ,566173743
00926 };
00927
00928
00932 void ddsInit()
00933 {
00934
00935 output_high (IO_CS);
00936 output_low (IO_PS1);
00937 output_low (IO_PS0);
00938 output_low (IO_OSK);
00939 output_low (IO_UPDATE);
00940
00941
00942 setup_spi( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_XMIT_L_TO_H );
00943
00944
00945 output_low (IO_OSK);
00946
00947 ddsSetMode (DDS_MODE_POWERDOWN);
00948
00949
00950 ddsSetOutputScale (0x3fff);
00951
00952
00953 output_low (IO_CS);
00954 spi_write (DDS_AD9954_ARR);
00955
00956 spi_write (181);
00957 output_high (IO_CS);
00958
00959
00960 output_low (IO_CS);
00961 spi_write (0x01);
00962
00963 spi_write (0x00);
00964 spi_write (0x00);
00965 spi_write (0xa4);
00966 output_high (IO_CS);
00967
00968
00969 output_high (IO_UPDATE);
00970 output_low (IO_UPDATE);
00971 }
00972
00979 void ddsSetOutputScale (uint16_t scale)
00980 {
00981
00982 output_low (IO_CS);
00983 spi_write (DDS_AD9954_ASF);
00984
00985 spi_write ((scale >> 8) & 0xff);
00986 spi_write (scale & 0xff);
00987
00988 output_high (IO_CS);
00989
00990
00991 output_high (IO_UPDATE);
00992 output_low (IO_UPDATE);
00993 }
00994
01001 void ddsSetAmplitude (uint8_t amplitude)
01002 {
01003
01004 if (amplitude > 200)
01005 return;
01006
01007
01008 ddsSetOutputScale (DDS_AMP_TO_SCALE[amplitude / 5]);
01009
01010
01011 output_low (IO_OSK);
01012 delay_ms(25);
01013
01014 output_high (IO_OSK);
01015 delay_ms(25);
01016 }
01017
01024 void ddsSetFreq(uint32_t freq)
01025 {
01026 uint8_t i;
01027 uint32_t ftw;
01028
01029
01030 ftw = freq * DDS_MULT[0];
01031
01032 for (i = 0; i < DDS_FREQ_TO_FTW_DIGITS - 1; ++i)
01033 ftw += (freq * DDS_MULT[i+1]) / DDS_DIVISOR[i];
01034
01035 ddsSetFTW (ftw);
01036 }
01037
01043 void ddsPhase (bool_t phase)
01044 {
01045
01046 output_low (IO_CS);
01047 spi_write (0x05);
01048
01049 if (phase)
01050 {
01051 spi_write (0x20);
01052 spi_write (0x00);
01053 } else {
01054 spi_write (0x00);
01055 spi_write (0x00);
01056 }
01057
01058 output_high (IO_CS);
01059
01060
01061 output_high (IO_UPDATE);
01062 output_low (IO_UPDATE);
01063 }
01064
01070 inline void ddsPTT (bool_t state)
01071 {
01072 if (state)
01073 output_high (IO_OSK);
01074 else
01075 output_low (IO_OSK);
01076 }
01077
01083 void ddsSetFTW (uint32_t ftw)
01084 {
01085
01086 output_low (IO_CS);
01087 spi_write (DDS_AD9954_FTW0);
01088
01089 spi_write ((ftw >> 24) & 0xff);
01090 spi_write ((ftw >> 16) & 0xff);
01091 spi_write ((ftw >> 8) & 0xff);
01092 spi_write (ftw & 0xff);
01093
01094 output_high (IO_CS);
01095
01096
01097 output_high (IO_UPDATE);
01098 output_low (IO_UPDATE);
01099 }
01100
01106 void ddsSetMode (DDS_MODE mode)
01107 {
01108 switch (mode)
01109 {
01110 case DDS_MODE_POWERDOWN:
01111
01112 output_low (IO_CS);
01113 spi_write (DDS_AD9954_CFR1);
01114
01115 spi_write (0x00);
01116 spi_write (0x00);
01117 spi_write (0x00);
01118 spi_write (0xf0);
01119 output_high (IO_CS);
01120 break;
01121
01122 case DDS_MODE_APRS:
01123
01124 output_low (IO_CS);
01125 spi_write (DDS_AD9954_CFR1);
01126
01127 spi_write (0x03);
01128 spi_write (0x00);
01129 spi_write (0x02);
01130 spi_write (0x40);
01131 output_high (IO_CS);
01132 break;
01133
01134 case DDS_MODE_PSK31:
01135
01136 output_low (IO_CS);
01137 spi_write (DDS_AD9954_CFR1);
01138
01139 spi_write (0x03);
01140 spi_write (0x00);
01141 spi_write (0x02);
01142 spi_write (0x40);
01143 output_high (IO_CS);
01144 break;
01145
01146 case DDS_MODE_HF_APRS:
01147
01148 output_low (IO_CS);
01149 spi_write (DDS_AD9954_CFR1);
01150
01151 spi_write (0x03);
01152 spi_write (0x20);
01153 spi_write (0x02);
01154 spi_write (0x40);
01155 output_high (IO_CS);
01156
01157
01158
01159
01160
01161
01162 output_low (IO_CS);
01163 spi_write (DDS_AD9954_NLSCW);
01164
01165 spi_write (36);
01166 spi_write (0x00);
01167 spi_write (0x00);
01168 spi_write (0x00);
01169 spi_write (0x01);
01170 output_high (IO_CS);
01171
01172
01173 output_low (IO_CS);
01174 spi_write (DDS_AD9954_PLSCW);
01175
01176 spi_write (36);
01177 spi_write (0x00);
01178 spi_write (0x00);
01179 spi_write (0x00);
01180 spi_write (0x01);
01181 output_high (IO_CS);
01182 break;
01183
01184 }
01185
01186
01187 output_high (IO_UPDATE);
01188 output_low (IO_UPDATE);
01189 }
01190
01202
01203 #define DIAG_BYTES_PER_LINE 32
01204
01208 void diagEraseFlash()
01209 {
01210
01211 fprintf (PC_HOST, "Are you sure (yes)? ");
01212
01213 if (fgetc(PC_HOST) != 'y')
01214 return;
01215
01216 if (fgetc(PC_HOST) != 'e')
01217 return;
01218
01219 if (fgetc(PC_HOST) != 's')
01220 return;
01221
01222 if (fgetc(PC_HOST) != 13)
01223 return;
01224
01225
01226 fprintf (PC_HOST, "\n\rErasing flash...");
01227
01228 flashErase();
01229
01230 fprintf (PC_HOST, "done.\n\r");
01231 }
01232
01236 void diagReadFlash()
01237 {
01238 bool_t dataFoundFlag, userStopFlag;
01239 uint8_t i, buffer[DIAG_BYTES_PER_LINE];
01240 uint32_t address;
01241
01242
01243 address = 0x0000;
01244 userStopFlag = false;
01245
01246 do
01247 {
01248
01249 flashReadBlock (address, buffer, DIAG_BYTES_PER_LINE);
01250
01251
01252 dataFoundFlag = false;
01253
01254
01255 fprintf (PC_HOST, "%03lx ", address);
01256
01257
01258 for (i = 0; i < DIAG_BYTES_PER_LINE; ++i)
01259 {
01260 fprintf (PC_HOST, "%02x", buffer[i]);
01261
01262
01263 if (buffer[i] != 0xff)
01264 dataFoundFlag = true;
01265
01266
01267 if (kbhit(PC_HOST))
01268 userStopFlag = true;
01269 }
01270
01271
01272 fprintf (PC_HOST, "\n\r");
01273
01274
01275 address += DIAG_BYTES_PER_LINE;
01276 } while (dataFoundFlag && !userStopFlag);
01277
01278
01279 if (userStopFlag)
01280 fprintf (PC_HOST, "User aborted download!\n\r");
01281 }
01282
01286 void diagMenu()
01287 {
01288
01289 fprintf (PC_HOST, "Options: (e)rase Flash, (r)ead Flash\n\r");
01290 fprintf (PC_HOST, " Toggle (L)ED, Toggle RF (P)A, Toggle Ban(d)\n\r");
01291 fprintf (PC_HOST, " Toggle (n)ichrome wire, Toggle ballast p(u)mp\n\r");
01292 fprintf (PC_HOST, " (t)emperature sensor value\n\r");
01293 fprintf (PC_HOST, " (f)requencey down, (F)requency up - 10Hz step\n\r");
01294 fprintf (PC_HOST, " (c)hannel down, (C)hannel up - 1KHz step\n\r");
01295 fprintf (PC_HOST, " (a)mplitude down, (A)mplitude up - 0.5 dB steps\n\r");
01296 fprintf (PC_HOST, " Re(b)oot processor\n\r");
01297 fprintf (PC_HOST, " e(x)it engineering mode\n\r");
01298 }
01299
01303 void diagPort()
01304 {
01305 bool_t diagDoneFlag, ledFlag, paFlag, showSettingsFlag, phaseFlag, cutdownFlag, pumpFlag;
01306 bool_t lowBandFlag;
01307 uint8_t command, amplitude;
01308 int16_t temperature, tcxo;
01309 uint32_t freqHz;
01310
01311
01312 if (!input(PIN_B6))
01313 return;
01314
01315 fprintf (PC_HOST, "Engineering Mode\n\r");
01316 fprintf (PC_HOST, "Application Built %s %s\n\r", __DATE__, __TIME__);
01317
01318
01319 ledFlag = false;
01320 output_bit (IO_LED, ledFlag);
01321
01322
01323 diagDoneFlag = false;
01324
01325
01326 paFlag = false;
01327
01328 cutdownFlag = false;
01329
01330 lowBandFlag = true;
01331
01332 pumpFlag = false;
01333
01334
01335 showSettingsFlag = false;
01336
01337
01338 freqHz = 14070450;
01339 amplitude = 100;
01340 phaseFlag = false;
01341
01342
01343 while (!diagDoneFlag)
01344 {
01345
01346 command = fgetc(PC_HOST);
01347
01348
01349 switch (command)
01350 {
01351 case 'e':
01352 diagEraseFlash();
01353 logInit();
01354 break;
01355
01356 case 's':
01357 fprintf (PC_HOST, "Flash Electronic Signature 0x%02x\n\r", flashReadElectronicSignature());
01358 break;
01359
01360
01361 case 'l':
01362 ledFlag = (ledFlag ? false : true);
01363 output_bit (IO_LED, ledFlag);
01364 break;
01365
01366
01367 case 'h':
01368 case 'H':
01369 case '?':
01370 diagMenu();
01371 break;
01372
01373 case 'r':
01374 diagReadFlash();
01375 break;
01376
01377
01378 case 'f':
01379 freqHz -= 100;
01380 ddsSetFreq (freqHz);
01381
01382
01383 showSettingsFlag = true;
01384 break;
01385
01386 case 'F':
01387 freqHz += 100;
01388 ddsSetFreq (freqHz);
01389
01390
01391 showSettingsFlag = true;
01392 break;
01393
01394
01395 case 'c':
01396 freqHz -= 10000;
01397 ddsSetFreq (freqHz);
01398
01399
01400 showSettingsFlag = true;
01401 break;
01402
01403 case 'C':
01404 freqHz += 10000;
01405 ddsSetFreq (freqHz);
01406
01407
01408 showSettingsFlag = true;
01409 break;
01410
01411 case 'a':
01412 if (amplitude != 200)
01413 {
01414 amplitude += 5;
01415 ddsSetAmplitude (amplitude);
01416
01417
01418 showSettingsFlag = true;
01419 }
01420 break;
01421
01422 case 'A':
01423 if (amplitude != 0)
01424 {
01425 amplitude -= 5;
01426 ddsSetAmplitude (amplitude);
01427
01428
01429 showSettingsFlag = true;
01430 }
01431 break;
01432
01433 case 'd':
01434 if (lowBandFlag)
01435 {
01436 lowBandFlag = false;
01437 freqHz = 50620000;
01438 } else {
01439 lowBandFlag = true;
01440 freqHz = 14070450;
01441 }
01442
01443
01444 showSettingsFlag = true;
01445 break;
01446
01447
01448
01449 case 'p':
01450 paFlag = (paFlag ? false : true);
01451 sysPAOutput (paFlag);
01452 output_bit (IO_OSK, paFlag);
01453
01454 if (paFlag)
01455 {
01456 ddsSetMode (DDS_MODE_PSK31);
01457 ddsSetFreq (freqHz);
01458 ddsSetAmplitude (amplitude);
01459 ddsPhase (phaseFlag);
01460 } else
01461 ddsSetMode (DDS_MODE_POWERDOWN);
01462
01463 break;
01464
01465 case 'x':
01466 diagDoneFlag = true;
01467 break;
01468
01469 case 't':
01470 temperature = lm92GetTemp();
01471 fprintf (PC_HOST, "%ld.%01ld degF\n\r", temperature / 10, temperature % 10);
01472 break;
01473
01474 case 'b':
01475 disable_interrupts (GLOBAL);
01476 fprintf (PC_HOST, "rebooting...\n\r\n\r");
01477 reset_cpu();
01478 break;
01479
01480 case '1':
01481 gpsPowerOn();
01482
01483 tcxo = 0x0000;
01484
01485 while (!kbhit(PC_HOST))
01486 {
01487 if (CCP_2 != tcxo)
01488 {
01489 fprintf (PC_HOST, "%ld %ld\n\r", CCP_2, CCP_2 - tcxo);
01490 tcxo = CCP_2;
01491 }
01492 }
01493
01494 gpsPowerOff();
01495 break;
01496
01497 case 'n':
01498 cutdownFlag = (cutdownFlag ? false : true);
01499 output_bit (IO_CUT_DOWN, cutdownFlag);
01500 break;
01501
01502 case 'u':
01503 pumpFlag = (pumpFlag ? false : true);
01504 output_bit (IO_BALLAST_PUMP, pumpFlag);
01505 break;
01506
01507 default:
01508 fprintf (PC_HOST, "Invalid command. (H)elp for menu.\n\r");
01509 break;
01510 }
01511
01512
01513 if (showSettingsFlag)
01514 {
01515 showSettingsFlag = false;
01516
01517 fprintf (PC_HOST, "%02ld.%06ldMHz ", freqHz / 1000000, freqHz % 1000000);
01518 fprintf (PC_HOST, "%d.%01ddBc\n\r", amplitude / 10, amplitude % 10);
01519 }
01520
01521 }
01522
01523
01524 fprintf (PC_HOST, "Exit diagnostic mode.\n\r");
01525
01526 return;
01527 }
01528
01544 bool_t flashIsWriteInProgress()
01545 {
01546 uint8_t status;
01547
01548 output_low (IO_FLASH_CS);
01549
01550
01551 flashSendByte (0x05);
01552
01553 status = flashGetByte();
01554
01555 output_high (IO_FLASH_CS);
01556
01557 return (((status & 0x01) == 0x01) ? true : false);
01558 }
01559
01567 void flashReadBlock(uint32_t address, uint8_t *block, uint16_t length)
01568 {
01569 uint16_t i;
01570
01571 output_low (IO_FLASH_CS);
01572
01573
01574 flashSendByte (0x03);
01575 flashSendAddress (address);
01576
01577 for (i = 0; i < length; ++i)
01578 *block++ = flashGetByte();
01579
01580 output_high (IO_FLASH_CS);
01581 }
01582
01590 void flashWriteBlock(uint32_t address, uint8_t *block, uint8_t length)
01591 {
01592 uint8_t i;
01593
01594 output_low (IO_FLASH_CS);
01595
01596 flashSendByte (0x06);
01597 output_high (IO_FLASH_CS);
01598
01599 output_low (IO_FLASH_CS);
01600
01601 flashSendByte (0x02);
01602 flashSendAddress (address);
01603
01604 for (i = 0; i < length; ++i)
01605 {
01606
01607 flashSendByte (*block++);
01608
01609
01610 ++address;
01611
01612
01613 if ((address & 0xff) == 0x00)
01614 {
01615 output_high (IO_FLASH_CS);
01616
01617
01618 while (flashIsWriteInProgress());
01619
01620 output_low (IO_FLASH_CS);
01621
01622 flashSendByte (0x06);
01623 output_high (IO_FLASH_CS);
01624
01625 output_low (IO_FLASH_CS);
01626
01627 flashSendByte (0x02);
01628 flashSendAddress (address);
01629 }
01630 }
01631
01632 output_high (IO_FLASH_CS);
01633
01634
01635 while (flashIsWriteInProgress());
01636 }
01637
01641 void flashErase()
01642 {
01643 output_low (IO_FLASH_CS);
01644
01645
01646 flashSendByte (0x06);
01647 output_high (IO_FLASH_CS);
01648
01649 output_low (IO_FLASH_CS);
01650
01651 flashSendByte (0xc7);
01652
01653 output_high (IO_FLASH_CS);
01654
01655 while (flashIsWriteInProgress());
01656 }
01657
01664 uint8_t flashReadElectronicSignature()
01665 {
01666 uint8_t electronicSignature;
01667
01668 output_low (IO_FLASH_CS);
01669 flashSendByte (0xab);
01670 flashSendByte (0x00);
01671 flashSendByte (0x00);
01672 flashSendByte (0x00);
01673
01674 electronicSignature = flashGetByte();
01675
01676 output_high (IO_FLASH_CS);
01677
01678 return electronicSignature;
01679 }
01680
01688 uint8_t flashGetByte()
01689 {
01690 return spi_read(0x00);
01691 }
01692
01696 void flashInit()
01697 {
01698
01699 output_high (IO_FLASH_CS);
01700 }
01701
01709 void flashSendByte(uint8_t value)
01710 {
01711 spi_write (value);
01712 }
01713
01721 void flashSendAddress(uint32_t address)
01722 {
01723 spi_write ((address >> 16) & 0xff);
01724 spi_write ((address >> 8) & 0xff);
01725 spi_write (address & 0xff);
01726 }
01727
01738
01739 #define GPS_BUFFER_SIZE 50
01740
01742 enum GPS_PARSE_STATE_MACHINE
01743 {
01745 GPS_START1,
01746
01748 GPS_START2,
01749
01751 GPS_COMMAND1,
01752
01754 GPS_COMMAND2,
01755
01757 GPS_READMESSAGE,
01758
01760 GPS_CHECKSUMMESSAGE,
01761
01763 GPS_EOMCR,
01764
01766 GPS_EOMLF
01767 };
01768
01770 uint8_t gpsIndex;
01771
01773 GPS_PARSE_STATE_MACHINE gpsParseState;
01774
01776 uint8_t gpsBuffer[GPS_BUFFER_SIZE];
01777
01779 int32_t gpsPeakAltitude;
01780
01782 uint8_t gpsChecksum;
01783
01789 GPS_FIX_TYPE gpsGetFixType()
01790 {
01791
01792 switch (gpsPosition.status & 0xe000)
01793 {
01794 case 0xe000:
01795 return GPS_3D_FIX;
01796
01797 case 0xc000:
01798 return GPS_2D_FIX;
01799
01800 default:
01801 return GPS_NO_FIX;
01802 }
01803 }
01804
01810 int32_t gpsGetPeakAltitude()
01811 {
01812 return gpsPeakAltitude;
01813 }
01814
01818 void gpsInit()
01819 {
01820
01821 gpsParseState = GPS_START1;
01822
01823
01824 gpsPeakAltitude = 0;
01825
01826
01827 memset (&gpsPosition, 0, sizeof(GPSPOSITION_STRUCT));
01828
01829
01830 setup_ccp2 (CCP_CAPTURE_RE);
01831 }
01832
01839 bool_t gpsIsReady()
01840 {
01841 if (gpsPosition.updateFlag)
01842 {
01843 gpsPosition.updateFlag = false;
01844 return true;
01845 }
01846
01847 return false;
01848 }
01849
01858 uint8_t gpsNMEAChecksum (uint8_t *buffer, uint8_t length)
01859 {
01860 uint8_t i, checksum;
01861
01862 checksum = 0;
01863
01864 for (i = 0; i < length; ++i)
01865 checksum ^= buffer[i];
01866
01867 return checksum;
01868 }
01869
01876 bool_t gpsSetup()
01877 {
01878 uint8_t startTime, retryCount;
01879
01880
01881 startTime = timeGetTicks();
01882 retryCount = 0;
01883
01884 while (++retryCount < 10)
01885 {
01886
01887 gpsUpdate();
01888
01889
01890 if (gpsIsReady())
01891 {
01892 timeSetDutyCycle (TIME_DUTYCYCLE_20);
01893 return true;
01894 }
01895
01896 if (timeGetTicks() > startTime)
01897 {
01898 puts ("@@Hb\001\053\015\012");
01899 startTime += 10;
01900 }
01901
01902 }
01903
01904 return false;
01905 }
01906
01910 void gpsParsePositionMessage()
01911 {
01912
01913
01914 gpsPosition.updateFlag = true;
01915
01916 gpsPosition.month = gpsBuffer[0];
01917 gpsPosition.day = gpsBuffer[1];
01918 gpsPosition.year = ((uint16_t) gpsBuffer[2] << 8) | gpsBuffer[3];
01919 gpsPosition.hours = gpsBuffer[4];
01920 gpsPosition.minutes = gpsBuffer[5];
01921 gpsPosition.seconds = gpsBuffer[6];
01922 gpsPosition.latitude = ((int32) gpsBuffer[11] << 24) | ((int32) gpsBuffer[12] << 16) | ((int32) gpsBuffer[13] << 8) | (int32) gpsBuffer[14];
01923 gpsPosition.longitude = ((int32) gpsBuffer[15] << 24) | ((int32) gpsBuffer[16] << 16) | ((int32) gpsBuffer[17] << 8) | gpsBuffer[18];
01924 gpsPosition.altitudeCM = ((int32) gpsBuffer[19] << 24) | ((int32) gpsBuffer[20] << 16) | ((int32) gpsBuffer[21] << 8) | gpsBuffer[22];
01925 gpsPosition.altitudeFeet = gpsPosition.altitudeCM * 100l / 3048l;
01926 gpsPosition.vSpeed = ((uint16_t) gpsBuffer[27] << 8) | gpsBuffer[28];
01927 gpsPosition.hSpeed = ((uint16_t) gpsBuffer[29] << 8) | gpsBuffer[30];
01928 gpsPosition.heading = ((uint16_t) gpsBuffer[31] << 8) | gpsBuffer[32];
01929 gpsPosition.dop = ((uint16_t) gpsBuffer[33] << 8) | gpsBuffer[34];
01930 gpsPosition.visibleSats = gpsBuffer[35];
01931 gpsPosition.trackedSats = gpsBuffer[36];
01932 gpsPosition.status = ((uint16_t) gpsBuffer[37] << 8) | gpsBuffer[38];
01933
01934
01935 if (gpsGetFixType() == GPS_3D_FIX)
01936 if (gpsPosition.altitudeFeet > gpsPeakAltitude)
01937 gpsPeakAltitude = gpsPosition.altitudeFeet;
01938 }
01939
01943 void gpsPowerOn()
01944 {
01945
01946 output_high (IO_GPS_PWR);
01947
01948
01949 SPEN = true;
01950 }
01951
01955 void gpsPowerOff()
01956 {
01957
01958 SPEN = false;
01959
01960
01961 output_low (IO_GPS_PWR);
01962 }
01963
01967 void gpsUpdate()
01968 {
01969 uint8_t value;
01970
01971
01972
01973 while (serialHasData()) {
01974
01975 value = serialRead();
01976
01977
01978 switch (gpsParseState)
01979 {
01980 case GPS_START1:
01981 if (value == '@')
01982 gpsParseState = GPS_START2;
01983 break;
01984
01985 case GPS_START2:
01986 if (value == '@')
01987 gpsParseState = GPS_COMMAND1;
01988 else
01989 gpsParseState = GPS_START1;
01990 break;
01991
01992 case GPS_COMMAND1:
01993 if (value == 'H')
01994 gpsParseState = GPS_COMMAND2;
01995 else
01996 gpsParseState = GPS_START1;
01997 break;
01998
01999 case GPS_COMMAND2:
02000 if (value == 'b')
02001 {
02002 gpsParseState = GPS_READMESSAGE;
02003 gpsIndex = 0;
02004 gpsChecksum = 0;
02005 gpsChecksum ^= 'H';
02006 gpsChecksum ^= 'b';
02007 } else
02008 gpsParseState = GPS_START1;
02009 break;
02010
02011 case GPS_READMESSAGE:
02012 gpsChecksum ^= value;
02013 gpsBuffer[gpsIndex++] = value;
02014
02015 if (gpsIndex == 47)
02016 gpsParseState = GPS_CHECKSUMMESSAGE;
02017
02018 break;
02019
02020 case GPS_CHECKSUMMESSAGE:
02021 if (gpsChecksum == value)
02022 gpsParseState = GPS_EOMCR;
02023 else
02024 gpsParseState = GPS_START1;
02025 break;
02026
02027 case GPS_EOMCR:
02028 if (value == 13)
02029 gpsParseState = GPS_EOMLF;
02030 else
02031 gpsParseState = GPS_START1;
02032 break;
02033
02034 case GPS_EOMLF:
02035
02036 if (value == 10)
02037 gpsParsePositionMessage();
02038
02039 gpsParseState = GPS_START1;
02040 break;
02041 }
02042 }
02043 }
02044
02055
02056 #define LOG_WRITE_BUFFER_SIZE 255
02057
02059 uint32_t logAddress;
02060
02062 uint8_t logBuffer[LOG_WRITE_BUFFER_SIZE];
02063
02065 uint8_t logIndex;
02066
02068 bool_t logDisableFlag;
02069
02076 uint32_t logGetAddress()
02077 {
02078 return logAddress;
02079 }
02080
02085 void logFlush()
02086 {
02087 if (logDisableFlag)
02088 return;
02089
02090
02091 if (logIndex != 0)
02092 {
02093 flashWriteBlock (logAddress, logBuffer, logIndex);
02094 logAddress += logIndex;
02095 logIndex = 0;
02096 }
02097 }
02098
02102 void logInit()
02103 {
02104 uint8_t buffer[8];
02105 bool_t endFound;
02106
02107
02108 logDisableFlag = false;
02109
02110 fprintf (PC_HOST, "Searching for end of flash log...");
02111
02112 logAddress = 0x0000;
02113 endFound = false;
02114
02115
02116 do
02117 {
02118
02119 flashReadBlock (logAddress, buffer, 1);
02120
02121
02122 switch (buffer[0])
02123 {
02124 case LOG_BOOTED:
02125 logAddress += 7;
02126 break;
02127
02128 case LOG_COORD:
02129 logAddress += 26;
02130 break;
02131
02132 case LOG_TEMPERATURE_1:
02133 case LOG_TEMPERATURE_2:
02134 logAddress += 3;
02135 break;
02136
02137 case LOG_VOLTAGE:
02138 logAddress += 5;
02139 break;
02140
02141 case LOG_PUMP:
02142 logAddress += 9;
02143 break;
02144
02145 case 0xff:
02146 endFound = true;
02147 break;
02148
02149 default:
02150 ++logAddress;
02151 }
02152 } while (logAddress < 0x100000 && !endFound);
02153
02154 fprintf (PC_HOST, "done.\n\rLog contains %ld bytes.\n\r", logAddress);
02155
02156 logIndex = 0;
02157 }
02158
02165 void logSetDisableFlag (bool_t disableFlag)
02166 {
02167 logDisableFlag = disableFlag;
02168 }
02169
02175 void logType (LOG_TYPE type)
02176 {
02177
02178 if (logAddress >= 0x100000)
02179 return;
02180
02181
02182 logFlush();
02183
02184
02185 logBuffer[logIndex++] = type;
02186 }
02187
02193 void logUint8 (uint8_t value)
02194 {
02195 logBuffer[logIndex++] = value;
02196 }
02197
02203 void logInt16 (int16_t value)
02204 {
02205 logBuffer[logIndex++] = (value >> 8) & 0xff;
02206 logBuffer[logIndex++] = value & 0xff;
02207 }
02208
02214 void logUint16 (uint16_t value)
02215 {
02216 logBuffer[logIndex++] = (value >> 8) & 0xff;
02217 logBuffer[logIndex++] = value & 0xff;
02218 }
02219
02225 void logInt32 (int32_t value)
02226 {
02227 logBuffer[logIndex++] = (value >> 24) & 0xff;
02228 logBuffer[logIndex++] = (value >> 16) & 0xff;
02229 logBuffer[logIndex++] = (value >> 8) & 0xff;
02230 logBuffer[logIndex++] = value & 0xff;
02231 }
02232
02243 #use i2c (master, scl=PIN_B5, sda=PIN_B1)
02244
02250 int16_t lm92GetTemp()
02251 {
02252 int16_t value;
02253 int32_t temp;
02254
02255
02256 i2c_start();
02257 i2c_write(0x97);
02258 value = ((int16_t) i2c_read() << 8);
02259 value = value | ((int16_t) i2c_read() & 0x00f8);
02260 i2c_stop();
02261
02262
02263
02264
02265
02266
02267 temp = (int32_t) value;
02268 temp = ((temp * 9l) / 64l) + 320;
02269
02270 return (int16_t) temp;
02271 }
02272
02282 const uint16_t PSK31_VARICODE[] =
02283 {
02284 0xAAC0,
02285 0xB6C0,
02286 0xBB40,
02287 0xDDC0,
02288 0xBAC0,
02289 0xD7C0,
02290 0xBBC0,
02291 0xBF40,
02292 0xBFC0,
02293 0xEF00,
02294 0xE800,
02295 0xDBC0,
02296 0xB740,
02297 0xF800,
02298 0xDD40,
02299 0xEAC0,
02300 0xBDC0,
02301 0xBD40,
02302 0xEB40,
02303 0xEBC0,
02304 0xD6C0,
02305 0xDAC0,
02306 0xDB40,
02307 0xD5C0,
02308 0xDEC0,
02309 0xDF40,
02310 0xEDC0,
02311 0xD540,
02312 0xD740,
02313 0xEEC0,
02314 0xBEC0,
02315 0xDFC0,
02316 0x8000,
02317 0xFF80,
02318 0xAF80,
02319 0xFA80,
02320 0xED80,
02321 0xB540,
02322 0xAEC0,
02323 0xBF80,
02324 0xFB00,
02325 0xF700,
02326 0xB780,
02327 0xEF80,
02328 0xEA00,
02329 0xD400,
02330 0xAE00,
02331 0xD780,
02332 0xB700,
02333 0xBD00,
02334 0xED00,
02335 0xFF00,
02336 0xBB80,
02337 0xAD80,
02338 0xB580,
02339 0xD680,
02340 0xD580,
02341 0xDB80,
02342 0xF500,
02343 0xDE80,
02344 0xF680,
02345 0xAA00,
02346 0xEB80,
02347 0xABC0,
02348 0xAF40,
02349 0xFA00,
02350 0xEB00,
02351 0xAD00,
02352 0xB500,
02353 0xEE00,
02354 0xDB00,
02355 0xFD00,
02356 0xAA80,
02357 0xFE00,
02358 0xFE80,
02359 0xBE80,
02360 0xD700,
02361 0xBB00,
02362 0xDD00,
02363 0xAB00,
02364 0xD500,
02365 0xEE80,
02366 0xAF00,
02367 0xDE00,
02368 0xDA00,
02369 0xAB80,
02370 0xDA80,
02371 0xAE80,
02372 0xBA80,
02373 0xBD80,
02374 0xAB40,
02375 0xFB80,
02376 0xF780,
02377 0xFD80,
02378 0xAFC0,
02379 0xB680,
02380 0xB7C0,
02381 0xB000,
02382 0xBE00,
02383 0xBC00,
02384 0xB400,
02385 0xC000,
02386 0xF400,
02387 0xB600,
02388 0xAC00,
02389 0xD000,
02390 0xF580,
02391 0xBF00,
02392 0xD800,
02393 0xEC00,
02394 0xF000,
02395 0xE000,
02396 0xFC00,
02397 0xDF80,
02398 0xA800,
02399 0xB800,
02400 0xA000,
02401 0xDC00,
02402 0xF600,
02403 0xD600,
02404 0xDF00,
02405 0xBA00,
02406 0xEA80,
02407 0xADC0,
02408 0xDD80,
02409 0xAD40,
02410 0xB5C0,
02411 0xED40
02412 };
02413
02415 #define PSK_MAX_PACKET 160
02416
02418 enum PSK_MODE
02419 {
02421 PSK_WAIT_MSG,
02422
02424 PSK_TX_SYNC,
02425
02427 PSK_TX_MESSAGE,
02428
02430 PSK_TX_END
02431 };
02432
02434 #define PSK31_TIMESLOT 0
02435
02437 #define PSK_SYNC_LENGTH 32
02438
02440 #define PSK_END_LENGTH 8
02441
02443 const uint32_t PSK31_FREQ_LIST[] = { 14070450, 14070450, 14070450 };
02444 const uint16_t PSK31_AMP_LIST[] = { 105, 105, 105 };
02445
02447 uint8_t pskCount;
02448
02450 uint16_t pskData;
02451
02453 bool_t pskPhase;
02454
02456 char pskBuffer[PSK_MAX_PACKET];
02457
02459 PSK_MODE pskMode;
02460
02462 uint8_t pskLastBits;
02463
02465 uint8_t pskIndex;
02466
02468 bool_t pskMessageDoneFlag;
02469
02474 bool_t psk31CreateDataPacket()
02475 {
02476 int32_t temp;
02477 int16_t temperature;
02478 uint32_t coord, coordMin;
02479
02480
02481 temperature = lm92GetTemp();
02482
02483 if (temperature == 0x13f)
02484 temperature = lm92GetTemp();
02485
02486 logType (LOG_TEMPERATURE_1);
02487 logInt16 (temperature);
02488
02489
02490 printf (psk31TxByte, "\n\n\nBalloon QSL www.kd7lmo.net\n");
02491
02492
02493 printf (psk31TxByte, "%02d%02dutc ", gpsPosition.hours, gpsPosition.minutes);
02494
02495
02496 if (gpsPosition.altitudeFeet > 1000)
02497 printf (psk31TxByte, "%ld,", gpsPosition.altitudeFeet / 1000);
02498
02499 printf (psk31TxByte, "%03ldft ", gpsPosition.altitudeFeet % 1000);
02500
02501
02502 coord = gpsPosition.latitude;
02503
02504 if (gpsPosition.latitude < 0)
02505 {
02506 coord = gpsPosition.latitude * -1;
02507 printf (psk31TxByte, "S");
02508 } else {
02509 coord = gpsPosition.latitude;
02510 printf (psk31TxByte, "N");
02511 }
02512
02513 coordMin = (coord % 3600000) / 600;
02514 printf (psk31TxByte, "%02ldd%02ld.%02ldm ", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 100), (uint32_t) (coordMin % 100));
02515
02516
02517 if (gpsPosition.longitude < 0)
02518 {
02519 coord = gpsPosition.longitude * - 1;
02520 printf (psk31TxByte, "W");
02521 } else {
02522 coord = gpsPosition.longitude;
02523 printf (psk31TxByte, "E");
02524 }
02525
02526 coordMin = (coord % 3600000) / 600;
02527 printf (psk31TxByte, "%03ldd%02ld.%02ldm ", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 100), (uint32_t) (coordMin % 100));
02528
02529
02530 temp = (int32_t) gpsPosition.hSpeed * 500 / 22352;
02531
02532 printf (psk31TxByte, "%ldmph@%ldd ", temp, gpsPosition.heading / 10);
02533
02534 printf (psk31TxByte, "%ld.%lddop ", gpsPosition.dop / 10, gpsPosition.dop % 10);
02535
02536 printf (psk31TxByte, "%ld.%ldF ", temperature / 10, abs(temperature % 10));
02537
02538 printf (psk31TxByte, "%ldp ", ballastGetPumpCount());
02539
02540 if (cutDownIsActivate())
02541 printf (psk31TxByte, "*");
02542
02543 printf (psk31TxByte, "\n");
02544
02545
02546 printf (psk31TxByte, "QSL www.kd7lmo.net de AC7ZT\n");
02547
02548
02549 printf (psk31TxByte, "\n\n\n");
02550
02551
02552 psk31TxNull();
02553
02554 return true;
02555 }
02556
02560 void psk31Init()
02561 {
02562 pskCount = 0;
02563 pskData = 0x0000;
02564 pskIndex = 0;
02565 pskMode = PSK_WAIT_MSG;
02566 pskPhase = false;
02567 pskLastBits = 0x00;
02568 pskMessageDoneFlag = false;
02569 }
02570
02576 bool_t psk31IsFree()
02577 {
02578 if (pskMode == PSK_WAIT_MSG)
02579 return true;
02580
02581 return false;
02582 }
02583
02587 void psk31TimeUpdate()
02588 {
02589
02590 if (pskMode == PSK_WAIT_MSG)
02591 return;
02592
02593
02594 if (pskCount == 15)
02595 if ((pskData & 0x8000) == 0x0000)
02596 output_low (IO_OSK);
02597
02598
02599 if (++pskCount == 32)
02600 {
02601 pskCount = 0;
02602
02603 switch (pskMode) {
02604 case PSK_TX_SYNC:
02605
02606 if (pskPhase)
02607 pskPhase = false;
02608 else
02609 pskPhase = true;
02610
02611 ddsPhase (pskPhase);
02612
02613
02614 if (--pskIndex == 0)
02615 {
02616 pskMode = PSK_TX_MESSAGE;
02617 pskIndex = 1;
02618 pskData = PSK31_VARICODE[pskBuffer[0]];
02619 pskLastBits = 0x0f;
02620 }
02621
02622
02623 output_high (IO_OSK);
02624
02625 break;
02626
02627 case PSK_TX_MESSAGE:
02628
02629 pskLastBits = (pskLastBits << 1) & 0x0f;
02630
02631
02632 if ((pskData & 0x8000) == 0x0000)
02633 {
02634 if (pskPhase)
02635 pskPhase = false;
02636 else
02637 pskPhase = true;
02638
02639 ddsPhase (pskPhase);
02640 } else
02641 pskLastBits |= 0x01;
02642
02643
02644 pskData = pskData << 1;
02645
02646
02647 if ((pskLastBits & 0x0c) == 0x00)
02648
02649 if (pskBuffer[pskIndex] == 0)
02650 {
02651 pskIndex = PSK_END_LENGTH;
02652 pskMode = PSK_TX_END;
02653 pskData = 0x0000;
02654 } else {
02655
02656 pskData = PSK31_VARICODE[pskBuffer[pskIndex++]];
02657
02658
02659 pskLastBits = 0x0f;
02660 }
02661
02662 output_high (IO_OSK);
02663
02664 break;
02665
02666 case PSK_TX_END:
02667
02668 if (pskPhase)
02669 pskPhase = false;
02670 else
02671 pskPhase = true;
02672
02673 ddsPhase (pskPhase);
02674
02675 if (--pskIndex == 0)
02676 {
02677
02678 output_low (IO_OSK);
02679
02680
02681 sysPAOutput (false);
02682
02683 ddsSetMode (DDS_MODE_POWERDOWN);
02684
02685 pskMessageDoneFlag = true;
02686
02687
02688 pskMode = PSK_WAIT_MSG;
02689
02690
02691 logSetDisableFlag (false);
02692 } else
02693 output_high (IO_OSK);
02694
02695 break;
02696 }
02697 }
02698 }
02699
02707 void psk31TxPacket(uint8_t minutes)
02708 {
02709
02710 if (pskMode != PSK_WAIT_MSG || !tncIsFree())
02711 return;
02712
02713
02714 if ((minutes % 6) != 0)
02715 return;
02716
02717
02718 logSetDisableFlag (true);
02719
02720
02721 pskIndex = 0;
02722
02723
02724 if (!psk31CreateDataPacket())
02725 {
02726 pskIndex = 0;
02727 printf (psk31TxByte, "Ballooon QSL www.kd7lmo.net * Unable to generate telemetry\n\n");
02728 psk31TxNull();
02729 }
02730
02731
02732 timeSetMode (TIME_MODE_PSK31);
02733
02734
02735 ddsSetMode (DDS_MODE_PSK31);
02736
02737
02738 ddsSetFreq (PSK31_FREQ_LIST[minutes % 3]);
02739 ddsSetAmplitude (PSK31_AMP_LIST[minutes % 3]);
02740
02741
02742 sysPAOutput (true);
02743
02744
02745 pskIndex = PSK_SYNC_LENGTH;
02746 pskCount = 0;
02747 pskData = 0x0000;
02748 pskMode = PSK_TX_SYNC;
02749 }
02750
02758 void psk31TxByte (uint8_t value)
02759 {
02760 if (pskIndex == PSK_MAX_PACKET)
02761 return;
02762
02763 pskBuffer[pskIndex++] = value;
02764 }
02765
02769 void psk31TxString (char *string, uint8_t length)
02770 {
02771 while (length-- != 0)
02772 psk31TxByte (*string++);
02773 }
02774
02775 void psk31TxNull ()
02776 {
02777 psk31TxByte (0x00);
02778 }
02779
02780 bool_t psk31IsMessageDone()
02781 {
02782 if (pskMessageDoneFlag)
02783 {
02784 pskMessageDoneFlag = false;
02785 return true;
02786 }
02787
02788 return false;
02789 }
02790
02801
02802 #define SERIAL_BUFFER_SIZE 64
02803
02805 #define SERIAL_BUFFER_MASK 0x3f
02806
02808 uint8_t serialHead;
02809
02811 uint8_t serialTail;
02812
02814 uint8_t serialBuffer[SERIAL_BUFFER_SIZE];
02815
02821 bool_t serialHasData()
02822 {
02823 if (serialHead == serialTail)
02824 return false;
02825
02826 return true;
02827 }
02828
02832 void serialInit()
02833 {
02834 serialHead = 0;
02835 serialTail = 0;
02836 }
02837
02843 uint8_t serialRead()
02844 {
02845 uint8_t value;
02846
02847
02848 if (serialHead == serialTail)
02849 return 0;
02850
02851
02852 value = serialBuffer[serialTail];
02853
02854
02855 serialTail = (serialTail + 1) & SERIAL_BUFFER_MASK;
02856
02857 return value;
02858 }
02859
02863 void serialUpdate()
02864 {
02865
02866 while (kbhit())
02867 {
02868
02869 serialBuffer[serialHead] = getc();
02870
02871
02872 serialHead = (serialHead + 1) & SERIAL_BUFFER_MASK;
02873 }
02874 }
02875
02889 void sysLogGPSData()
02890 {
02891
02892 logType (LOG_COORD);
02893 logUint8 (gpsPosition.hours);
02894 logUint8 (gpsPosition.minutes);
02895 logUint8 (gpsPosition.seconds);
02896 logInt32 (gpsPosition.latitude);
02897 logInt32 (gpsPosition.longitude);
02898 logInt32 (gpsPosition.altitudeCM);
02899
02900 logUint16 (gpsPosition.vSpeed);
02901 logUint16 (gpsPosition.hSpeed);
02902 logUint16 (gpsPosition.heading);
02903
02904 logUint16 (gpsPosition.status);
02905
02906 logUint8 ((uint8_t) (gpsPosition.dop & 0xff));
02907 logUint8 ((uint8_t) ((gpsPosition.visibleSats << 4) | gpsPosition.trackedSats));
02908 }
02909
02920 uint16_t sysCRC16(uint8_t *buffer, uint8_t length, uint16_t crc)
02921 {
02922 uint8_t i, bit, value;
02923
02924 for (i = 0; i < length; ++i)
02925 {
02926 value = buffer[i];
02927
02928 for (bit = 0; bit < 8; ++bit) {
02929 crc ^= (value & 0x01);
02930 crc = ( crc & 0x01 ) ? ( crc >> 1 ) ^ 0x8408 : ( crc >> 1 );
02931 value = value >> 1;
02932 }
02933 }
02934
02935 return crc ^ 0xffff;
02936 }
02937
02943 inline void sysPAOutput (bool_t state)
02944 {
02945 if (state)
02946 output_low (IO_PA);
02947 else
02948 output_high (IO_PA);
02949 }
02950
02961
02962 uint8_t timeTicks;
02963
02965 uint16_t timeInterruptCount;
02966
02968 uint8_t time100ms;
02969
02971 uint8_t timeSeconds;
02972
02974 uint8_t timeMinutes;
02975
02977 uint8_t timeHours;
02978
02980 uint8_t timeDutyCycle;
02981
02983 uint16_t timeCompare;
02984
02986 uint16_t timeRate;
02987
02989 bool_t timeUpdateFlag;
02990
02992 bool_t timeRunFlag;
02993
02995 uint16_t timeInterruptCountRollOver;
02996
02998 TIME_MODE timeMode;
02999
03001 #define TIME_RATE_PSK31 4800
03002 #define TIME_RATE_APRS 500
03003 #define TIME_RATE_HF_APRS 16000
03004
03006 #define TIME_ROLLOVER_PSK31 100
03007 #define TIME_ROLLOVER_APRS 960
03008 #define TIME_ROLLOVER_HF_APRS 30
03009
03015 uint8_t timeGetTicks()
03016 {
03017 return timeTicks;
03018 }
03019
03023 void timeInit()
03024 {
03025 timeTicks = 0;
03026 timeInterruptCount = 0;
03027 time100mS = 0;
03028 timeSeconds = 0;
03029 timeMinutes = 0;
03030 timeHours = 0;
03031 timeDutyCycle = TIME_DUTYCYCLE_70;
03032 timeCompare = TIME_RATE_APRS;
03033 timeUpdateFlag = false;
03034 timeRate = TIME_RATE_APRS;
03035 timeRunFlag = false;
03036 timeUpdateFlag = false;
03037 timeInterruptCountRollOver = TIME_ROLLOVER_APRS;
03038 timeMode = TIME_MODE_APRS;
03039
03040
03041 CCP_1 = timeRate;
03042 set_timer1(timeCompare);
03043 setup_ccp1( CCP_COMPARE_INT );
03044 setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 );
03045 }
03046
03052 uint8_t timeGetHours()
03053 {
03054 return timeHours;
03055 }
03056
03062 uint8_t timeGetMinutes()
03063 {
03064 return timeMinutes;
03065 }
03066
03072 void timeSetDutyCycle (uint8_t dutyCycle)
03073 {
03074 timeDutyCycle = dutyCycle;
03075 }
03076
03081 void timeSetRunFlag()
03082 {
03083 timeRunFlag = true;
03084 }
03085
03091 void timeSetMode (TIME_MODE mode)
03092 {
03093
03094 if (mode == timeMode)
03095 return;
03096
03097
03098 timeMode = mode;
03099
03100
03101 disable_interrupts (INT_CCP1);
03102
03103 switch (timeMode) {
03104 case TIME_MODE_APRS:
03105 timeRate = TIME_RATE_APRS;
03106 timeInterruptCountRollOver = TIME_ROLLOVER_APRS;
03107 break;
03108
03109 case TIME_MODE_PSK31:
03110 timeRate = TIME_RATE_PSK31;
03111 timeInterruptCountRollOver = TIME_ROLLOVER_PSK31;
03112 break;
03113
03114 case TIME_MODE_HF_APRS:
03115 timeRate = TIME_RATE_HF_APRS;
03116 timeInterruptCountRollOver = TIME_ROLLOVER_HF_APRS;
03117 break;
03118 }
03119
03120
03121
03122 timeInterruptCount = timeInterruptCount % timeInterruptCountRollOver;
03123
03124
03125 enable_interrupts (INT_CCP1);
03126 }
03127
03128
03129 #INT_CCP1
03130 void timeUpdate()
03131 {
03132
03133 output_high (PIN_B1);
03134
03135
03136 timeCompare += timeRate;
03137 CCP_1 = timeCompare;
03138
03139
03140 if (timeMode == TIME_MODE_PSK31)
03141 psk31TimeUpdate();
03142 else
03143 tncTimeUpdate();
03144
03145
03146 serialUpdate();
03147
03148
03149 if (++timeInterruptCount == timeInterruptCountRollOver)
03150 {
03151 timeInterruptCount = 0;
03152
03153
03154 ++timeTicks;
03155
03156
03157 if (++time100mS == 10)
03158 {
03159 time100mS = 0;
03160
03161
03162 timeUpdateFlag = true;
03163
03164
03165 if (timeRunFlag)
03166 if (++timeSeconds == 60)
03167 {
03168 timeSeconds = 0;
03169
03170 if (++timeMinutes == 60)
03171 {
03172 timeMinutes = 0;
03173 ++timeHours;
03174 }
03175 }
03176 }
03177
03178
03179 if (time100mS >= timeDutyCycle)
03180 output_low (IO_LED);
03181 else
03182 output_high (IO_LED);
03183 }
03184
03185
03186 output_low (PIN_B1);
03187 }
03188
03199
03200 #define TNC_TX_DELAY 45
03201
03203 #define TNC_TIMESLOT 55
03204
03206 enum TNC_MODE
03207 {
03209 TNC_TX_READY,
03210
03212 TNC_TX_SYNC,
03213
03215 TNC_TX_HEADER,
03216
03218 TNC_TX_DATA,
03219
03221 TNC_TX_END
03222 };
03223
03224
03225 #define TNC_BUFFER_SIZE 80
03226
03227
03228 #define TNC_DWELL_TIME 3600
03229
03230
03231 uint8_t TNC_AX25_HEADER[30] =
03232 {
03233 'A' << 1, 'P' << 1, 'R' << 1, 'S' << 1, ' ' << 1, ' ' << 1, 0x60, \
03234 'K' << 1, 'D' << 1, '7' << 1, 'L' << 1, 'M' << 1, 'O' << 1, 0x76, \
03235 'G' << 1, 'A' << 1, 'T' << 1, 'E' << 1, ' ' << 1, ' ' << 1, 0x60, \
03236 'W' << 1, 'I' << 1, 'D' << 1, 'E' << 1, '3' << 1, ' ' << 1, 0x67, \
03237 0x03, 0xf0
03238 };
03239
03240 uint8_t tncLastBit;
03241 uint8_t tncPacketType;
03242
03244 TNC_MODE tncMode;
03245
03247 uint8_t tncBitCount;
03248
03250 uint8_t tncShift;
03251
03253 uint8_t tncIndex;
03254
03256 uint8_t tncLength;
03257
03259 uint8_t tncBitStuff;
03260
03262 uint8_t *tncBufferPnt;
03263
03265 uint8_t tncBuffer[TNC_BUFFER_SIZE];
03266
03267
03268 uint16_t tncTestCount;
03269
03271 uint16_t timeNCO;
03272
03274 uint16_t timeNCOFreq;
03275
03277 uint8_t timeLowRateCount;
03278
03279 void tncInit()
03280 {
03281 tncLastBit = 0;
03282 tncMode = TNC_TX_READY;
03283 tncTestCount = 0;
03284 tncPacketType = TNC_BOOT_MESSAGE;
03285 timeNCO = 0x00;
03286 timeLowRateCount = 0;
03287 timeNCOFreq = 0x2000;
03288 }
03289
03295 bool_t tncIsFree()
03296 {
03297 if (tncMode == TNC_TX_READY)
03298 return true;
03299
03300 return false;
03301 }
03302
03303
03304
03305 void tncTimeUpdate()
03306 {
03307
03308 if (tncMode == TNC_TX_READY)
03309 return;
03310
03311
03312 ddsSetFTW (freqTable[timeNCO >> 8]);
03313
03314
03315 timeNCO += timeNCOFreq;
03316
03317 if (++timeLowRateCount == 8)
03318 {
03319 timeLowRateCount = 0;
03320
03321
03322 if (tncLastBit == 0x00)
03323 timeNCOFreq = 0x2000;
03324 else
03325 timeNCOFreq = 0x3aab;
03326
03327 switch (tncMode)
03328 {
03329 case TNC_TX_SYNC:
03330
03331
03332 if ((tncShift & 0x01) == 0x00)
03333 if (tncLastBit == 0)
03334 tncLastBit = 1;
03335 else
03336 tncLastBit = 0;
03337
03338
03339 if (++tncBitCount == 8)
03340 {
03341 tncBitCount = 0;
03342 tncShift = 0x7e;
03343
03344
03345
03346 if (++tncIndex == TNC_TX_DELAY)
03347 {
03348 tncIndex = 0;
03349 tncShift = TNC_AX25_HEADER[0];
03350 tncBitStuff = 0;
03351 tncMode = TNC_TX_HEADER;
03352 }
03353 } else
03354 tncShift = tncShift >> 1;
03355 break;
03356
03357 case TNC_TX_HEADER:
03358
03359 if (tncBitStuff == 0x1f)
03360 {
03361 if (tncLastBit == 0)
03362 tncLastBit = 1;
03363 else
03364 tncLastBit = 0;
03365
03366 tncBitStuff = 0x00;
03367 return;
03368 }
03369
03370
03371
03372 if ((tncShift & 0x01) == 0x00)
03373 if (tncLastBit == 0)
03374 tncLastBit = 1;
03375 else
03376 tncLastBit = 0;
03377
03378
03379
03380 tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;
03381
03382
03383 if (++tncBitCount == 8)
03384 {
03385 tncBitCount = 0;
03386
03387
03388 if (++tncIndex == sizeof(TNC_AX25_HEADER))
03389 {
03390 tncIndex = 0;
03391 tncShift = tncBuffer[0];
03392 tncMode = TNC_TX_DATA;
03393 } else
03394 tncShift = TNC_AX25_HEADER[tncIndex];
03395
03396 } else
03397 tncShift = tncShift >> 1;
03398
03399 break;
03400
03401 case TNC_TX_DATA:
03402
03403 if (tncBitStuff == 0x1f)
03404 {
03405 if (tncLastBit == 0)
03406 tncLastBit = 1;
03407 else
03408 tncLastBit = 0;
03409
03410 tncBitStuff = 0x00;
03411 return;
03412 }
03413
03414
03415
03416 if ((tncShift & 0x01) == 0x00)
03417 if (tncLastBit == 0)
03418 tncLastBit = 1;
03419 else
03420 tncLastBit = 0;
03421
03422
03423
03424 tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;
03425
03426
03427 if (++tncBitCount == 8)
03428 {
03429 tncBitCount = 0;
03430
03431
03432 if (++tncIndex == tncLength)
03433 {
03434 tncIndex = 0;
03435 tncShift = 0x7e;
03436 tncMode = TNC_TX_END;
03437 } else
03438 tncShift = tncBuffer[tncIndex];
03439
03440 } else
03441 tncShift = tncShift >> 1;
03442
03443 break;
03444
03445 case TNC_TX_END:
03446
03447
03448 if ((tncShift & 0x01) == 0x00)
03449 if (tncLastBit == 0)
03450 tncLastBit = 1;
03451 else
03452 tncLastBit = 0;
03453
03454
03455 if (++tncBitCount == 8)
03456 {
03457 tncBitCount = 0;
03458 tncShift = 0x7e;
03459
03460
03461 if (++tncIndex == 2)
03462 {
03463
03464 ddsPTT (false);
03465 sysPAOutput (false);
03466 ddsSetMode (DDS_MODE_POWERDOWN);
03467
03468 tncMode = TNC_TX_READY;
03469
03470
03471 logSetDisableFlag (false);
03472 return;
03473 }
03474 } else
03475 tncShift = tncShift >> 1;
03476
03477 break;
03478 }
03479 }
03480 }
03481
03489 void tncTxByte (uint8_t value)
03490 {
03491 *tncBufferPnt++ = value;
03492 ++tncLength;
03493 }
03494
03499 void tncNMEATime()
03500 {
03501
03502 printf (tncTxByte, "%02d%02d%02d,", gpsPosition.hours, gpsPosition.minutes, gpsPosition.seconds);
03503 }
03504
03509 void tncNMEAFix()
03510 {
03511 uint8_t dirChar;
03512 uint32_t coord, coordMin;
03513
03514
03515 coord = gpsPosition.latitude;
03516
03517 if (gpsPosition.latitude < 0)
03518 {
03519 coord = gpsPosition.latitude * -1;
03520 dirChar = 'S';
03521 } else {
03522 coord = gpsPosition.latitude;
03523 dirChar = 'N';
03524 }
03525
03526 coordMin = (coord % 3600000) / 6;
03527 printf (tncTxByte, "%02ld%02ld.%04ld,%c,", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 10000), (uint32_t) (coordMin % 10000), dirChar);
03528
03529
03530
03531 if (gpsPosition.longitude < 0) {
03532 coord = gpsPosition.longitude * - 1;
03533 dirChar = 'W';
03534 } else {
03535 coord = gpsPosition.longitude;
03536 dirChar = 'E';
03537 }
03538
03539 coordMin = (coord % 3600000) / 6;
03540 printf (tncTxByte, "%03ld%02ld.%04ld,%c,", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 10000), (uint32_t) (coordMin % 10000), dirChar);
03541 }
03542
03547 void tncStatusPacket()
03548 {
03549 int16_t temperature;
03550
03551
03552 printf (tncTxByte, ">Balloon ");
03553
03554
03555 printf (tncTxByte, "%03U:%02U:%02U ", timeHours, timeMinutes, timeSeconds);
03556
03557
03558 printf (tncTxByte, "%ld' ", gpsPosition.altitudeFeet);
03559
03560
03561 printf (tncTxByte, "%lu.%lu", gpsPosition.dop / 10, gpsPosition.dop % 10);
03562
03563
03564 switch (gpsGetFixType())
03565 {
03566 case GPS_NO_FIX:
03567 printf (tncTxByte, "dop ");
03568 break;
03569
03570 case GPS_2D_FIX:
03571 printf (tncTxByte, "hdop ");
03572 break;
03573
03574 case GPS_3D_FIX:
03575 printf (tncTxByte, "pdop ");
03576 break;
03577 }
03578
03579
03580 printf (tncTxByte, "%utrk ", gpsPosition.trackedSats);
03581
03582
03583 temperature = lm92GetTemp();
03584
03585 printf (tncTxByte, "%ld.%ldF ", temperature / 10, abs(temperature % 10));
03586
03587
03588 printf (tncTxByte, "QSL www.kd7lmo.net");
03589 }
03590
03595 void tncGPGGAPacket()
03596 {
03597
03598 printf (tncTxByte, "$GPGGA,");
03599
03600
03601 tncNMEATime();
03602
03603
03604 tncNMEAFix();
03605
03606
03607 if (gpsGetFixType() != GPS_NO_FIX)
03608 printf (tncTxByte, "1,");
03609 else
03610 printf (tncTxByte, "0,");
03611
03612
03613 printf (tncTxByte, "%02d,", gpsPosition.trackedSats);
03614
03615
03616 printf (tncTxByte, "%ld.%01ld,", gpsPosition.dop / 10, gpsPosition.dop % 10);
03617
03618
03619 printf (tncTxByte, "%ld.%02ld,M,,M,,", (int32_t) (gpsPosition.altitudeCM / 100l), (int32_t) (gpsPosition.altitudeCM % 100));
03620
03621
03622 printf (tncTxByte, "*%02X", gpsNMEAChecksum(tncBuffer + 1, tncLength - 1));
03623 }
03624
03629 void tncGPRMCPacket()
03630 {
03631 uint32_t temp;
03632
03633
03634 printf (tncTxByte, "$GPRMC,");
03635
03636
03637 tncNMEATime();
03638
03639
03640 if (gpsGetFixType() != GPS_NO_FIX)
03641 printf (tncTxByte, "A,");
03642 else
03643 printf (tncTxByte, "V,");
03644
03645
03646 tncNMEAFix();
03647
03648
03649 temp = (int32_t) gpsPosition.hSpeed * 75000 / 385826;
03650 printf (tncTxByte, "%ld.%ld,%ld.%ld,", (int16_t) (temp / 10), (int16_t) (temp % 10), gpsPosition.heading / 10, gpsPosition.heading % 10);
03651
03652
03653 printf (tncTxByte, "%02d%02d%02ld,,", gpsPosition.day, gpsPosition.month, gpsPosition.year % 100);
03654
03655
03656 printf (tncTxByte, "*%02X", gpsNMEAChecksum(tncBuffer + 1, tncLength - 1));
03657 }
03658
03663 void tncTxPacket(TNC_PACKET_TYPE tncPacketType)
03664 {
03665 uint16_t crc;
03666
03667
03668 if (tncMode != TNC_TX_READY || !psk31IsFree())
03669 return;
03670
03671
03672 logSetDisableFlag (true);
03673
03674
03675 tncBufferPnt = tncBuffer;
03676
03677
03678 tncLength = 0;
03679
03680
03681 switch (tncPacketType)
03682 {
03683 case TNC_BOOT_MESSAGE:
03684 printf (tncTxByte, ">ANSR PSK-31/APRS Beacon - V1.07");
03685 break;
03686
03687 case TNC_STATUS:
03688 tncStatusPacket();
03689 break;
03690
03691 case TNC_GGA:
03692 tncGPGGAPacket();
03693 break;
03694
03695 case TNC_RMC:
03696 tncGPRMCPacket();
03697 break;
03698 }
03699
03700
03701 printf (tncTxByte, "\015");
03702
03703
03704 crc = sysCRC16(TNC_AX25_HEADER, sizeof(TNC_AX25_HEADER), 0xffff);
03705 crc = sysCRC16(tncBuffer, tncLength, crc ^ 0xffff);
03706
03707
03708 *tncBufferPnt++ = crc & 0xff;
03709 *tncBufferPnt = (crc >> 8) & 0xff;
03710
03711
03712 tncLength += 2;
03713
03714
03715 timeSetMode (TIME_MODE_APRS);
03716
03717
03718 ddsSetMode (DDS_MODE_APRS);
03719
03720
03721 ddsSetAmplitude (105);
03722
03723
03724 tncBitCount = 0;
03725 tncShift = 0x7e;
03726 tncLastBit = 0;
03727 tncIndex = 0;
03728 tncMode = TNC_TX_SYNC;
03729
03730
03731 ddsPTT (true);
03732 sysPAOutput (true);
03733 }
03734
03737
03738 void main()
03739 {
03740 uint8_t utcSeconds, utcMinutes, lockLostCounter;
03741
03742
03743 output_low (IO_GPS_PWR);
03744 output_high (IO_LED);
03745
03746 output_low (IO_CUT_DOWN);
03747 output_high (IO_PA);
03748
03749
03750 setup_adc_ports( NO_ANALOGS );
03751
03752
03753 set_tris_a (0x00);
03754 set_tris_b (0x62);
03755 set_tris_c (0x92);
03756
03757
03758 ballastInit();
03759 cutDownInit();
03760 gpsInit();
03761 timeInit();
03762 psk31Init();
03763 serialInit();
03764 tncInit();
03765
03766
03767 delay_ms (400);
03768
03769
03770 ddsInit();
03771
03772
03773 logInit();
03774
03775
03776 output_low (IO_LED);
03777
03778
03779 diagPort();
03780
03781
03782 enable_interrupts(GLOBAL);
03783 enable_interrupts(INT_CCP1);
03784
03785
03786 output_high (IO_GPS_PWR);
03787
03788
03789 delay_ms (100);
03790
03791
03792 while (!gpsSetup());
03793
03794
03795 logType (LOG_BOOTED);
03796 logUint8 (gpsPosition.month);
03797 logUint8 (gpsPosition.day);
03798 logUint8 (gpsPosition.year & 0xff);
03799
03800 logUint8 (gpsPosition.hours);
03801 logUint8 (gpsPosition.minutes);
03802 logUint8 (gpsPosition.seconds);
03803
03804
03805 lockLostCounter = 0;
03806 utcSeconds = gpsPosition.seconds;
03807 utcMinutes = gpsPosition.minutes;
03808
03809
03810 tncTxPacket(TNC_BOOT_MESSAGE);
03811
03812
03813 for (;;)
03814 {
03815
03816 gpsUpdate();
03817
03818 if (gpsIsReady())
03819 {
03820
03821 if (gpsGetFixType() == GPS_3D_FIX)
03822 {
03823 timeSetRunFlag();
03824 timeSetDutyCycle (TIME_DUTYCYCLE_0);
03825 }
03826
03827
03828 switch (gpsPosition.seconds)
03829 {
03830 case TNC_TIMESLOT:
03831 switch (gpsPosition.minutes % 3)
03832 {
03833 case 0:
03834 tncTxPacket(TNC_STATUS);
03835 break;
03836
03837 case 1:
03838 tncTxPacket(TNC_GGA);
03839 break;
03840
03841 case 2:
03842 tncTxPacket(TNC_RMC);
03843 break;
03844 }
03845
03846 break;
03847
03848 case PSK31_TIMESLOT:
03849 psk31TxPacket(gpsPosition.minutes);
03850 break;
03851 }
03852
03853
03854 utcSeconds = gpsPosition.seconds;
03855
03856 lockLostCounter = 0;
03857
03858
03859 if ((gpsPosition.seconds % 10) == 0)
03860 sysLogGPSData();
03861
03862
03863 ballastCheck();
03864
03865 cutDownCheck();
03866 }
03867
03868
03869 if (timeUpdateFlag)
03870 {
03871
03872 if (++utcSeconds == 60)
03873 {
03874 utcSeconds = 0;
03875
03876 if (++utcMinutes == 60)
03877 utcMinutes = 0;
03878 }
03879
03880
03881 if (lockLostCounter == 5)
03882 {
03883
03884 switch (utcSeconds)
03885 {
03886 case TNC_TIMESLOT:
03887 switch (gpsPosition.minutes % 3)
03888 {
03889 case 0:
03890 tncTxPacket(TNC_STATUS);
03891 break;
03892
03893 case 1:
03894 tncTxPacket(TNC_GGA);
03895 break;
03896
03897 case 2:
03898 tncTxPacket(TNC_RMC);
03899 break;
03900 }
03901
03902 break;
03903
03904 case PSK31_TIMESLOT:
03905 psk31TxPacket(utcMinutes);
03906 break;
03907 }
03908 } else
03909 ++lockLostCounter;
03910
03911
03912 timeUpdateFlag = false;
03913 }
03914
03915 if (psk31IsMessageDone())
03916 {
03917
03918 logType (LOG_TEMPERATURE_2);
03919 logInt16 (lm92GetTemp());
03920 }
03921
03922 }
03923 }