00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <time.h>
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <unistd.h>
00022 #include <math.h>
00023 #include <ctype.h>
00024 #include <asterisk/ulaw.h>
00025 #include <asterisk/tdd.h>
00026 #include <asterisk/logger.h>
00027 #include <asterisk/fskmodem.h>
00028 #include "ecdisa.h"
00029
00030
00031 struct tdd_state {
00032 fsk_data fskd;
00033 char rawdata[256];
00034 short oldstuff[4096];
00035 int oldlen;
00036 int pos;
00037 int modo;
00038 int mode;
00039 };
00040
00041 static float dr[4], di[4];
00042 static float tddsb = 176.0;
00043
00044 #define TDD_SPACE 1800.0
00045 #define TDD_MARK 1400.0
00046
00047 static int tdd_decode_baudot(struct tdd_state *tdd,unsigned char data)
00048 {
00049 static char ltrs[32]={'<','E','\n','A',' ','S','I','U',
00050 '\n','D','R','J','N','F','C','K',
00051 'T','Z','L','W','H','Y','P','Q',
00052 'O','B','G','^','M','X','V','^'};
00053 static char figs[32]={'<','3','\n','-',' ',',','8','7',
00054 '\n','$','4','\'',',','·',':','(',
00055 '5','+',')','2','·','6','0','1',
00056 '9','7','·','^','.','/','=','^'};
00057 int d;
00058 d=0;
00059 switch (data) {
00060 case 0x1f : tdd->modo=0; break;
00061 case 0x1b : tdd->modo=1; break;
00062 default: if (tdd->modo==0) d=ltrs[data]; else d=figs[data]; break;
00063 }
00064 return d;
00065 }
00066
00067 void tdd_init(void)
00068 {
00069
00070 dr[0] = cos(TDD_SPACE * 2.0 * M_PI / 8000.0);
00071 di[0] = sin(TDD_SPACE * 2.0 * M_PI / 8000.0);
00072 dr[1] = cos(TDD_MARK * 2.0 * M_PI / 8000.0);
00073 di[1] = sin(TDD_MARK * 2.0 * M_PI / 8000.0);
00074 }
00075
00076 struct tdd_state *tdd_new(void)
00077 {
00078 struct tdd_state *tdd;
00079 tdd = malloc(sizeof(struct tdd_state));
00080 if (tdd) {
00081 memset(tdd, 0, sizeof(struct tdd_state));
00082 tdd->fskd.spb = 176;
00083 tdd->fskd.hdlc = 0;
00084 tdd->fskd.nbit = 5;
00085 tdd->fskd.nstop = 1.5;
00086 tdd->fskd.paridad = 0;
00087 tdd->fskd.bw=0;
00088 tdd->fskd.f_mark_idx = 0;
00089 tdd->fskd.f_space_idx = 1;
00090 tdd->fskd.pcola = 0;
00091 tdd->fskd.cont = 0;
00092 tdd->fskd.x0 = 0.0;
00093 tdd->fskd.state = 0;
00094 tdd->pos = 0;
00095 tdd->mode = 2;
00096 } else
00097 ast_log(LOG_WARNING, "Out of memory\n");
00098 return tdd;
00099 }
00100
00101 int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
00102 {
00103 int pos = 0;
00104 int cnt;
00105 while(len) {
00106 cnt = len;
00107 if (cnt > sizeof(ecdisa))
00108 cnt = sizeof(ecdisa);
00109 memcpy(outbuf + pos, ecdisa, cnt);
00110 pos += cnt;
00111 len -= cnt;
00112 }
00113 return 0;
00114 }
00115
00116 int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int len)
00117 {
00118 int mylen = len;
00119 int olen;
00120 int b = 'X';
00121 int res;
00122 int c,x;
00123 short *buf = malloc(2 * len + tdd->oldlen);
00124 short *obuf = buf;
00125 if (!buf) {
00126 ast_log(LOG_WARNING, "Out of memory\n");
00127 return -1;
00128 }
00129 memset(buf, 0, 2 * len + tdd->oldlen);
00130 memcpy(buf, tdd->oldstuff, tdd->oldlen);
00131 mylen += tdd->oldlen/2;
00132 for (x=0;x<len;x++)
00133 buf[x+tdd->oldlen/2] = AST_MULAW(ubuf[x]);
00134 c = res = 0;
00135 while(mylen >= 1320) {
00136 olen = mylen;
00137 res = fsk_serie(&tdd->fskd, buf, &mylen, &b);
00138 if (mylen < 0) {
00139 ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d) (olen was %d)\n", mylen,olen);
00140 free(obuf);
00141 return -1;
00142 }
00143 buf += (olen - mylen);
00144 if (res < 0) {
00145 ast_log(LOG_NOTICE, "fsk_serie failed\n");
00146 free(obuf);
00147 return -1;
00148 }
00149 if (res == 1) {
00150
00151 if (b > 0x7f)
00152 continue;
00153 c = tdd_decode_baudot(tdd,b);
00154 if ((c < 1) || (c > 126)) continue;
00155 break;
00156 }
00157 }
00158 if (mylen) {
00159 memcpy(tdd->oldstuff, buf, mylen * 2);
00160 tdd->oldlen = mylen * 2;
00161 } else
00162 tdd->oldlen = 0;
00163 free(obuf);
00164 if (res) {
00165 tdd->mode = 2;
00166
00167 return(c);
00168 }
00169 return 0;
00170 }
00171
00172 void tdd_free(struct tdd_state *tdd)
00173 {
00174 free(tdd);
00175 }
00176
00177 static inline float tdd_getcarrier(float *cr, float *ci, int bit)
00178 {
00179
00180 float t;
00181 t = *cr * dr[bit] - *ci * di[bit];
00182 *ci = *cr * di[bit] + *ci * dr[bit];
00183 *cr = t;
00184
00185 t = 2.0 - (*cr * *cr + *ci * *ci);
00186 *cr *= t;
00187 *ci *= t;
00188 return *cr;
00189 }
00190
00191 #define PUT_BYTE(a) do { \
00192 *(buf++) = (a); \
00193 bytes++; \
00194 } while(0)
00195
00196 #define PUT_AUDIO_SAMPLE(y) do { \
00197 int index = (short)(rint(8192.0 * (y))); \
00198 *(buf++) = AST_LIN2MU(index); \
00199 bytes++; \
00200 } while(0)
00201
00202 #define PUT_TDD_MARKMS do { \
00203 int x; \
00204 for (x=0;x<8;x++) \
00205 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
00206 } while(0)
00207
00208 #define PUT_TDD_BAUD(bit) do { \
00209 while(scont < tddsb) { \
00210 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, bit)); \
00211 scont += 1.0; \
00212 } \
00213 scont -= tddsb; \
00214 } while(0)
00215
00216 #define PUT_TDD_STOP do { \
00217 while(scont < (tddsb * 1.5)) { \
00218 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
00219 scont += 1.0; \
00220 } \
00221 scont -= (tddsb * 1.5); \
00222 } while(0)
00223
00224
00225 #define PUT_TDD(byte) do { \
00226 int z; \
00227 unsigned char b = (byte); \
00228 PUT_TDD_BAUD(0); \
00229 for (z=0;z<5;z++) { \
00230 PUT_TDD_BAUD(b & 1); \
00231 b >>= 1; \
00232 } \
00233 PUT_TDD_STOP; \
00234 } while(0);
00235
00236 int tdd_generate(struct tdd_state *tdd, unsigned char *buf, char *str)
00237 {
00238 int bytes=0;
00239 int i,x;
00240 char c;
00241 static unsigned char lstr[31] = "\000E\nA SIU\rDRJNFCKTZLWHYPQOBG\000MXV";
00242 static unsigned char fstr[31] = "\0003\n- \00787\r$4',!:(5\")2\0006019?&\000./;";
00243
00244 float cr = 1.0;
00245 float ci = 0.0;
00246 float scont = 0.0;
00247
00248 for(x = 0; str[x]; x++) {
00249 c = toupper(str[x]);
00250 #if 0
00251 printf("%c",c); fflush(stdout);
00252 #endif
00253 if (c == 0)
00254 {
00255 PUT_TDD(0);
00256 continue;
00257 }
00258 if (c == '\r')
00259 {
00260 PUT_TDD(8);
00261 continue;
00262 }
00263 if (c == '\n')
00264 {
00265 PUT_TDD(8);
00266 PUT_TDD(2);
00267 continue;
00268 }
00269 if (c == ' ')
00270 {
00271 PUT_TDD(4);
00272 continue;
00273 }
00274 for(i = 0; i < 31; i++)
00275 {
00276 if (lstr[i] == c) break;
00277 }
00278 if (i < 31)
00279 {
00280 if (tdd->mode)
00281 {
00282 PUT_TDD(31);
00283 tdd->mode = 0;
00284 }
00285 PUT_TDD(i);
00286 continue;
00287 }
00288 for(i = 0; i < 31; i++)
00289 {
00290 if (fstr[i] == c) break;
00291 }
00292 if (i < 31)
00293 {
00294 if (tdd->mode != 1)
00295 {
00296 PUT_TDD(27);
00297 tdd->mode = 1;
00298 }
00299 PUT_TDD(i);
00300 continue;
00301 }
00302 }
00303 return bytes;
00304 }
00305
00306