sm_afsk2400_7.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*****************************************************************************/
  2. /*
  3.  * sm_afsk2400_7.c  -- soundcard radio modem driver, 2400 baud AFSK modem
  4.  *
  5.  * Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *  Please note that the GPL allows you to use the driver, NOT the radio.
  22.  *  In order to use the radio, you need a license from the communications
  23.  *  authority of your country.
  24.  *
  25.  */
  26. /*
  27.  * This driver is intended to be compatible with TCM3105 modems
  28.  * overclocked to 7.3728MHz. The mark and space frequencies therefore
  29.  * lie at 3658 and 1996 Hz.
  30.  * Note that I do _not_ recommend the building of such links, I provide
  31.  * this only for the users who live in the coverage area of such
  32.  * a "legacy" link.
  33.  */
  34. #include "sm.h"
  35. #include "sm_tbl_afsk2400_7.h"
  36. /* --------------------------------------------------------------------- */
  37. struct demod_state_afsk24 {
  38. unsigned int shreg;
  39. unsigned int bit_pll;
  40. unsigned char last_sample;
  41. unsigned int dcd_shreg;
  42. int dcd_sum0, dcd_sum1, dcd_sum2;
  43. unsigned int dcd_time;
  44. unsigned char last_rxbit;
  45. };
  46. struct mod_state_afsk24 {
  47. unsigned int shreg;
  48. unsigned char tx_bit;
  49. unsigned int bit_pll;
  50. unsigned int tx_seq;
  51. unsigned int phinc;
  52. };
  53. /* --------------------------------------------------------------------- */
  54. static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE,
  55. AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE };
  56. static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
  57. {
  58. struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
  59. for (; buflen > 0; buflen--, buf++) {
  60. if (st->tx_seq < 0x5555) {
  61. if (st->shreg <= 1)
  62. st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
  63. st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
  64. st->shreg >>= 1;
  65. st->phinc = dds_inc[st->tx_bit & 1];
  66. }
  67. st->tx_seq += 0x5555;
  68. st->tx_seq &= 0xffff;
  69. *buf = OFFSCOS(st->bit_pll);
  70. st->bit_pll += st->phinc;
  71. }
  72. }
  73. /* --------------------------------------------------------------------- */
  74. static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen)
  75. {
  76. struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
  77. for (; buflen > 0; buflen--, buf++) {
  78. if (st->tx_seq < 0x5555) {
  79. if (st->shreg <= 1)
  80. st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
  81. st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
  82. st->shreg >>= 1;
  83. st->phinc = dds_inc[st->tx_bit & 1];
  84. }
  85. st->tx_seq += 0x5555;
  86. st->tx_seq &= 0xffff;
  87. *buf = COS(st->bit_pll);
  88. st->bit_pll += st->phinc;
  89. }
  90. }
  91. /* --------------------------------------------------------------------- */
  92. static inline int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
  93. {
  94. int sum = -0x80 * csum;
  95. sum += (st[0] * coeff[0]);
  96. sum += (st[-1] * coeff[1]);
  97. sum += (st[-2] * coeff[2]);
  98. sum += (st[-3] * coeff[3]);
  99. sum += (st[-4] * coeff[4]);
  100. sum += (st[-5] * coeff[5]);
  101. sum += (st[-6] * coeff[6]);
  102. sum += (st[-7] * coeff[7]);
  103. sum += (st[-8] * coeff[8]);
  104. sum += (st[-9] * coeff[9]);
  105. sum += (st[-10] * coeff[10]);
  106. sum += (st[-11] * coeff[11]);
  107. sum += (st[-12] * coeff[12]);
  108. sum += (st[-13] * coeff[13]);
  109. sum >>= 7;
  110. return sum * sum;
  111. }
  112. static inline int convolution14_s16(const short *st, const int *coeff, int csum)
  113. {
  114. int sum = 0;
  115. sum += (st[0] * coeff[0]);
  116. sum += (st[-1] * coeff[1]);
  117. sum += (st[-2] * coeff[2]);
  118. sum += (st[-3] * coeff[3]);
  119. sum += (st[-4] * coeff[4]);
  120. sum += (st[-5] * coeff[5]);
  121. sum += (st[-6] * coeff[6]);
  122. sum += (st[-7] * coeff[7]);
  123. sum += (st[-8] * coeff[8]);
  124. sum += (st[-9] * coeff[9]);
  125. sum += (st[-10] * coeff[10]);
  126. sum += (st[-11] * coeff[11]);
  127. sum += (st[-12] * coeff[12]);
  128. sum += (st[-13] * coeff[13]);
  129. sum >>= 15;
  130. return sum * sum;
  131. }
  132. static inline int do_filter_2400_u8(const unsigned char *buf)
  133. {
  134. int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
  135. sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
  136. sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
  137. sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
  138. return sum;
  139. }
  140. static inline int do_filter_2400_s16(const short *buf)
  141. {
  142. int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
  143. sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
  144. sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
  145. sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
  146. return sum;
  147. }
  148. /* --------------------------------------------------------------------- */
  149. static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
  150. {
  151. struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
  152. int j;
  153. int sum;
  154. unsigned char newsample;
  155. for (; buflen > 0; buflen--, buf++) {
  156. sum = do_filter_2400_u8(buf);
  157. st->dcd_shreg <<= 1;
  158. st->bit_pll += AFSK24_BITPLL_INC;
  159. newsample = (sum > 0);
  160. if (st->last_sample ^ newsample) {
  161. st->last_sample = newsample;
  162. st->dcd_shreg |= 1;
  163. if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
  164. st->bit_pll += AFSK24_BITPLL_INC/2;
  165. else
  166. st->bit_pll -= AFSK24_BITPLL_INC/2;
  167. j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
  168. - hweight16(st->dcd_shreg & 0x1e0);
  169. st->dcd_sum0 += j;
  170. }
  171. hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
  172. if ((--st->dcd_time) <= 0) {
  173. hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
  174.    st->dcd_sum1 + 
  175.    st->dcd_sum2) < 0);
  176. st->dcd_sum2 = st->dcd_sum1;
  177. st->dcd_sum1 = st->dcd_sum0;
  178. st->dcd_sum0 = 2; /* slight bias */
  179. st->dcd_time = 120;
  180. }
  181. if (st->bit_pll >= 0x10000) {
  182. st->bit_pll &= 0xffff;
  183. st->shreg >>= 1;
  184. st->shreg |= (!(st->last_rxbit ^
  185. st->last_sample)) << 16;
  186. st->last_rxbit = st->last_sample;
  187. diag_trigger(sm);
  188. if (st->shreg & 1) {
  189. hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
  190. st->shreg = 0x10000;
  191. }
  192. }
  193. diag_add(sm, (((int)*buf)-0x80) << 8, sum);
  194. }
  195. }
  196. /* --------------------------------------------------------------------- */
  197. static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
  198. {
  199. struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
  200. int j;
  201. int sum;
  202. unsigned char newsample;
  203. for (; buflen > 0; buflen--, buf++) {
  204. sum = do_filter_2400_s16(buf);
  205. st->dcd_shreg <<= 1;
  206. st->bit_pll += AFSK24_BITPLL_INC;
  207. newsample = (sum > 0);
  208. if (st->last_sample ^ newsample) {
  209. st->last_sample = newsample;
  210. st->dcd_shreg |= 1;
  211. if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
  212. st->bit_pll += AFSK24_BITPLL_INC/2;
  213. else
  214. st->bit_pll -= AFSK24_BITPLL_INC/2;
  215. j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
  216. - hweight16(st->dcd_shreg & 0x1e0);
  217. st->dcd_sum0 += j;
  218. }
  219. hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
  220. if ((--st->dcd_time) <= 0) {
  221. hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
  222.    st->dcd_sum1 + 
  223.    st->dcd_sum2) < 0);
  224. st->dcd_sum2 = st->dcd_sum1;
  225. st->dcd_sum1 = st->dcd_sum0;
  226. st->dcd_sum0 = 2; /* slight bias */
  227. st->dcd_time = 120;
  228. }
  229. if (st->bit_pll >= 0x10000) {
  230. st->bit_pll &= 0xffff;
  231. st->shreg >>= 1;
  232. st->shreg |= (!(st->last_rxbit ^
  233. st->last_sample)) << 16;
  234. st->last_rxbit = st->last_sample;
  235. diag_trigger(sm);
  236. if (st->shreg & 1) {
  237. hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
  238. st->shreg = 0x10000;
  239. }
  240. }
  241. diag_add(sm, *buf, sum);
  242. }
  243. }
  244. /* --------------------------------------------------------------------- */
  245. static void demod_init_2400(struct sm_state *sm)
  246. {
  247. struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
  248.         st->dcd_time = 120;
  249. st->dcd_sum0 = 2;
  250. }
  251. /* --------------------------------------------------------------------- */
  252. const struct modem_tx_info sm_afsk2400_7_tx = {
  253. "afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, 
  254. modulator_2400_u8, modulator_2400_s16, NULL
  255. };
  256. const struct modem_rx_info sm_afsk2400_7_rx = {
  257. "afsk2400_7", sizeof(struct demod_state_afsk24), 
  258. AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, 
  259. demodulator_2400_u8, demodulator_2400_s16, demod_init_2400
  260. };
  261. /* --------------------------------------------------------------------- */