diff options
-rw-r--r-- | src/amps/amps.h | 5 | ||||
-rw-r--r-- | src/amps/dsp.c | 166 | ||||
-rw-r--r-- | src/amps/frame.c | 38 | ||||
-rw-r--r-- | src/amps/frame.h | 4 | ||||
-rw-r--r-- | src/amps/main.c | 33 | ||||
-rw-r--r-- | src/amps/sysinfo.c | 8 | ||||
-rw-r--r-- | src/amps/sysinfo.h | 2 |
7 files changed, 130 insertions, 126 deletions
diff --git a/src/amps/amps.h b/src/amps/amps.h index b067f70..a6b0302 100644 --- a/src/amps/amps.h +++ b/src/amps/amps.h @@ -31,7 +31,7 @@ enum fsk_rx_sync { FSK_SYNC_NEGATIVE, /* as above, but negative sync (high frequency deviation detected as low signal) */ }; -#define FSK_MAX_BITS 1032 /* maximum number of bits to process */ +#define FSK_MAX_BITS 1032 /* maximum number of bits to process (FVC with dotting+sync) */ typedef struct amps { sender_t sender; @@ -44,6 +44,7 @@ typedef struct amps { enum amps_chan_type chan_type; enum amps_state state; int page_retry; /* current number of paging (re)try */ + int channel_busy; /* indicate channel is busy while receiving */ /* system info */ amps_si si; @@ -60,6 +61,8 @@ typedef struct amps { double fsk_bitduration; /* duration of one bit in samples */ double fsk_bitstep; /* fraction of one bit each sample */ /* tx bits generation */ + char fsk_tx_frame[FSK_MAX_BITS + 1]; /* +1 because 0-termination */ + int fsk_tx_frame_pos; /* current position sending bits */ int16_t *fsk_tx_buffer; /* tx buffer for one data block */ int fsk_tx_buffer_size; /* size of tx buffer (in samples) */ int fsk_tx_buffer_length; /* usage of buffer (in samples) */ diff --git a/src/amps/dsp.c b/src/amps/dsp.c index 45fbf1e..1be5fbe 100644 --- a/src/amps/dsp.c +++ b/src/amps/dsp.c @@ -158,7 +158,7 @@ int dsp_init_sender(amps_t *amps, int high_pass) amps->fsk_bitstep = 1.0 / amps->fsk_bitduration; PDEBUG(DDSP, DEBUG_DEBUG, "Use %.4f samples for full bit duration @ %d.\n", amps->fsk_bitduration, amps->sender.samplerate); - amps->fsk_tx_buffer_size = amps->fsk_bitduration * (double)FSK_MAX_BITS + 10; /* 10 extra to avoid overflow due to routing */ + amps->fsk_tx_buffer_size = amps->fsk_bitduration + 10; /* 10 extra to avoid overflow due to rounding */ amps->fsk_tx_buffer = calloc(sizeof(int16_t), amps->fsk_tx_buffer_size); if (!amps->fsk_tx_buffer) { PDEBUG(DDSP, DEBUG_DEBUG, "No memory!\n"); @@ -237,76 +237,66 @@ void dsp_cleanup_sender(amps_t *amps) #endif } -static int fsk_encode(amps_t *amps, const char *bits) +static int fsk_encode(amps_t *amps, char bit) { int16_t *spl; double phase, bitstep, deviation; int count; char last; - if (strlen(bits) > FSK_MAX_BITS) { - fprintf(stderr, "FSK buffer too small\n"); - abort(); - } - deviation = amps->fsk_deviation; spl = amps->fsk_tx_buffer; phase = amps->fsk_tx_phase; last = amps->fsk_tx_last_bit; bitstep = amps->fsk_bitstep * 256.0 * 2.0; /* half bit ramp */ -//printf("%s\n", bits); - while (*bits) { -//printf("%d %d\n", (*bits) & 1, last & 1); - if (((*bits) & 1)) { - if ((last & 1)) { - /* last bit was 1, this bit is 1, so we ramp down first */ - do { - *spl++ = ramp_down[(int)phase]; - phase += bitstep; - } while (phase < 256.0); - phase -= 256.0; - } else { - /* last bit was 0, this bit is 1, so we stay down first */ - do { - *spl++ = -deviation; - phase += bitstep; - } while (phase < 256.0); - phase -= 256.0; - } - /* ramp up */ +//printf("%d %d\n", (bit) & 1, last & 1); + if ((bit & 1)) { + if ((last & 1)) { + /* last bit was 1, this bit is 1, so we ramp down first */ do { - *spl++ = ramp_up[(int)phase]; + *spl++ = ramp_down[(int)phase]; phase += bitstep; } while (phase < 256.0); phase -= 256.0; } else { - if ((last & 1)) { - /* last bit was 1, this bit is 0, so we stay up first */ - do { - *spl++ = deviation; - phase += bitstep; - } while (phase < 256.0); - phase -= 256.0; - } else { - /* last bit was 0, this bit is 0, so we ramp up first */ - do { - *spl++ = ramp_up[(int)phase]; - phase += bitstep; - } while (phase < 256.0); - phase -= 256.0; - } - /* ramp up */ + /* last bit was 0, this bit is 1, so we stay down first */ do { - *spl++ = ramp_down[(int)phase]; + *spl++ = -deviation; phase += bitstep; } while (phase < 256.0); phase -= 256.0; } - last = *bits; - bits++; - } - + /* ramp up */ + do { + *spl++ = ramp_up[(int)phase]; + phase += bitstep; + } while (phase < 256.0); + phase -= 256.0; + } else { + if ((last & 1)) { + /* last bit was 1, this bit is 0, so we stay up first */ + do { + *spl++ = deviation; + phase += bitstep; + } while (phase < 256.0); + phase -= 256.0; + } else { + /* last bit was 0, this bit is 0, so we ramp up first */ + do { + *spl++ = ramp_up[(int)phase]; + phase += bitstep; + } while (phase < 256.0); + phase -= 256.0; + } + /* ramp up */ + do { + *spl++ = ramp_down[(int)phase]; + phase += bitstep; + } while (phase < 256.0); + phase -= 256.0; + } + last = bit; /* depending on the number of samples, return the number */ count = ((uintptr_t)spl - (uintptr_t)amps->fsk_tx_buffer) / sizeof(*spl); @@ -319,46 +309,60 @@ static int fsk_encode(amps_t *amps, const char *bits) int fsk_frame(amps_t *amps, int16_t *samples, int length) { - int count = 0, pos, copy, i; + int count = 0, len, pos, copy, i; int16_t *spl; - const char *bits; + int rc; + char c; + + len = amps->fsk_tx_buffer_length; + pos = amps->fsk_tx_buffer_pos; + spl = amps->fsk_tx_buffer; again: /* there must be length, otherwise we would skip blocks */ if (count == length) - return count; - - pos = amps->fsk_tx_buffer_pos; - spl = amps->fsk_tx_buffer + pos; + goto done; - /* start new frame, so we generate one */ + /* start of new bit, so generate buffer for one bit */ if (pos == 0) { - if (amps->dsp_mode == DSP_MODE_AUDIO_RX_FRAME_TX) - bits = amps_encode_frame_fvc(amps); - else - bits = amps_encode_frame_focc(amps); - if (!bits) - return 0; - fsk_encode(amps, bits); + c = amps->fsk_tx_frame[amps->fsk_tx_frame_pos]; + /* start new frame, so we generate one */ + if (c == '\0') { + if (amps->dsp_mode == DSP_MODE_AUDIO_RX_FRAME_TX) + rc = amps_encode_frame_fvc(amps, amps->fsk_tx_frame); + else + rc = amps_encode_frame_focc(amps, amps->fsk_tx_frame); + /* check if we have not bit string (change to tx audio) + * we may not store fsk_tx_buffer_pos, because is was reset on a mode achange */ + if (rc) + return count; + amps->fsk_tx_frame_pos = 0; + c = amps->fsk_tx_frame[0]; + } + if (c == 'i') + c = (amps->channel_busy) ? '0' : '1'; + len = fsk_encode(amps, c); + amps->fsk_tx_frame_pos++; } - copy = amps->fsk_tx_buffer_length - pos; + copy = len - pos; if (length - count < copy) copy = length - count; //printf("pos=%d length=%d copy=%d\n", pos, length, copy); for (i = 0; i < copy; i++) { #ifdef DEBUG_ENCODER - puts(debug_amplitude((double)(*spl) / 32767.0)); + puts(debug_amplitude((double)spl[pos] / 32767.0)); #endif - *samples++ = *spl++; + *samples++ = spl[pos++]; } - pos += copy; count += copy; - if (pos ==amps->fsk_tx_buffer_length) { - amps->fsk_tx_buffer_pos = 0; + if (pos == len) { + pos = 0; goto again; } +done: + amps->fsk_tx_buffer_length = len; amps->fsk_tx_buffer_pos = pos; return count; @@ -399,12 +403,10 @@ void sender_send(sender_t *sender, int16_t *samples, int length) again: switch (amps->dsp_mode) { case DSP_MODE_OFF: -off: /* silence, if transmitter is off */ memset(samples, 0, length * sizeof(*samples)); break; case DSP_MODE_AUDIO_RX_AUDIO_TX: -audio: jitter_load(&s->sender.audio, samples, length); /* pre-emphasis */ if (amps->pre_emphasis) @@ -417,21 +419,10 @@ audio: /* Encode frame into audio stream. If frames have * stopped, process again for rest of stream. */ count = fsk_frame(amps, samples, length); -#if 0 - /* special case: add SAT signal to frame at loop test */ - if (amps->sender.loopback) - sat_encode(amps, samples, length); -#endif - /* count == 0: no frame, this should not happen */ - if (count == 0) - goto off; - /* * also if the mode changed to audio during processing */ - if (amps->dsp_mode == DSP_MODE_AUDIO_RX_AUDIO_TX) - goto audio; samples += count; length -= count; - goto again; - break; + if (length) + goto again; } } @@ -512,6 +503,7 @@ prepare_frame: printf("No Sync detected after dotting\n"); #endif amps->fsk_rx_sync = FSK_SYNC_NONE; + amps->channel_busy = 0; return; } return; @@ -549,6 +541,7 @@ prepare_frame: if (amps->fsk_rx_frame_length == 240) amps->fsk_rx_frame_length = 247; amps->fsk_rx_sync = FSK_SYNC_NONE; + amps->channel_busy = 0; } } } @@ -599,6 +592,8 @@ void fsk_rx_dotting(amps_t *amps, double _elapsed, int dir) amps->fsk_rx_sync = FSK_SYNC_DOTTING; amps->fsk_rx_dotting_average = fabs(average); amps->fsk_rx_bitcount = 0.5 + average; + if (amps->si.acc_type.bis) + amps->channel_busy = 1; } } @@ -859,9 +854,12 @@ void amps_set_dsp_mode(amps_t *amps, enum dsp_mode mode, int frame_length) /* reset detection process */ amps->fsk_rx_sync = FSK_SYNC_NONE; + amps->channel_busy = 0; amps->fsk_rx_sync_register = 0x555; /* reset transmitter */ amps->fsk_tx_buffer_pos = 0; + amps->fsk_tx_frame[0] = '\0'; + amps->fsk_tx_frame_pos = 0; } diff --git a/src/amps/frame.c b/src/amps/frame.c index bc3d039..58261ff 100644 --- a/src/amps/frame.c +++ b/src/amps/frame.c @@ -3285,22 +3285,21 @@ static uint64_t string2bin(const char *string) } #endif -static char *amps_encode_focc_bits(amps_t *amps, uint64_t word_a, uint64_t word_b, int busy_idle) +void amps_encode_focc_bits(amps_t *amps, uint64_t word_a, uint64_t word_b, char *bits) { - static char bits[463 + 1]; int i, j, k; strncpy(bits + 0, dotting, 10); - bits[10] = (busy_idle) ? '1' : '0'; + bits[10] = 'i'; strcpy(bits + 11, sync_word); - bits[22] = (busy_idle) ? '1' : '0'; + bits[22] = 'i'; /* WORD A (msb first) */ k = 23; for (i = 0; i < 5; i++) { for (j = 39; j >= 0; j--) { bits[k++] = ((word_a >> j) & 1) + '0'; if ((j % 10) == 0) - bits[k++] = (busy_idle) ? '1' : '0'; + bits[k++] = 'i'; } } /* WORD B (msb first) */ @@ -3308,7 +3307,7 @@ static char *amps_encode_focc_bits(amps_t *amps, uint64_t word_a, uint64_t word_ for (j = 39; j >= 0; j--) { bits[k++] = ((word_b >> j) & 1) + '0'; if ((j % 10) == 0) - bits[k++] = (busy_idle) ? '1' : '0'; + bits[k++] = 'i'; } } @@ -3335,13 +3334,10 @@ static char *amps_encode_focc_bits(amps_t *amps, uint64_t word_a, uint64_t word_ } #endif } - - return bits; } -static char *amps_encode_fvc_bits(amps_t *amps, uint64_t word_a) +void amps_encode_fvc_bits(amps_t *amps, uint64_t word_a, char *bits) { - static char bits[1032 + 1]; int i, j, k; @@ -3369,13 +3365,10 @@ static char *amps_encode_fvc_bits(amps_t *amps, uint64_t word_a) PDEBUG(DFRAME, DEBUG_INFO, "TX FVC: %s\n", bits); } #endif - - return bits; } -const char *amps_encode_frame_focc(amps_t *amps) +int amps_encode_frame_focc(amps_t *amps, char *bits) { - char *bits; uint64_t word; /* init overhead train */ @@ -3406,7 +3399,7 @@ const char *amps_encode_frame_focc(amps_t *amps) } /* on change of dsp mode */ if (amps->dsp_mode != DSP_MODE_FRAME_RX_FRAME_TX) - return NULL; + return 1; } /* send scheduled mobile control message */ if (amps->tx_focc_send) { @@ -3439,7 +3432,7 @@ const char *amps_encode_frame_focc(amps_t *amps) amps->tx_focc_frame_count = 0; send: - bits = amps_encode_focc_bits(amps, word, word, 1); + amps_encode_focc_bits(amps, word, word, bits); /* invert, if polarity of the cell is negative */ if (amps->flip_polarity) { @@ -3449,12 +3442,11 @@ send: bits[i] ^= 1; } - return bits; + return 0; } -const char *amps_encode_frame_fvc(amps_t *amps) +int amps_encode_frame_fvc(amps_t *amps, char *bits) { - char *bits; uint64_t word; /* see if we can schedule a mobile control message */ @@ -3470,7 +3462,7 @@ const char *amps_encode_frame_fvc(amps_t *amps) } /* on change of dsp mode */ if (amps->dsp_mode != DSP_MODE_AUDIO_RX_FRAME_TX) - return NULL; + return 1; } /* send scheduled mobile control message */ @@ -3481,9 +3473,9 @@ const char *amps_encode_frame_fvc(amps_t *amps) else word = amps_encode_mobile_station_control_message_word1_a(amps->sat, amps->tx_fvc_msg_type, amps->tx_fvc_ordq, amps->tx_fvc_order); } else - return NULL; + return 1; - bits = amps_encode_fvc_bits(amps, word); + amps_encode_fvc_bits(amps, word, bits); /* invert, if polarity of the cell is negative */ if (amps->flip_polarity) { @@ -3493,7 +3485,7 @@ const char *amps_encode_frame_fvc(amps_t *amps) bits[i] ^= 1; } - return bits; + return 0; } /* assemble FOCC bits */ diff --git a/src/amps/frame.h b/src/amps/frame.h index c8195cb..9531dfe 100644 --- a/src/amps/frame.h +++ b/src/amps/frame.h @@ -219,7 +219,7 @@ uint64_t amps_encode_new_access_channel_set(uint8_t dcc, uint16_t newacc, uint8_ uint64_t amps_encode_overload_control(uint8_t dcc, uint8_t *olc, uint8_t end); uint64_t amps_encode_access_type(uint8_t dcc, uint8_t bis, uint8_t pci_home, uint8_t pci_roam, uint8_t bspc, uint8_t bscap, uint8_t end); uint64_t amps_encode_access_attempt(uint8_t dcc, uint8_t maxbusy_pgr, uint8_t maxsztr_pgr, uint8_t maxbusy_other, uint8_t maxsztr_other, uint8_t end); -const char *amps_encode_frame_focc(amps_t *amps); -const char *amps_encode_frame_fvc(amps_t *amps); +int amps_encode_frame_focc(amps_t *amps, char *bits); +int amps_encode_frame_fvc(amps_t *amps, char *bits); int amps_decode_frame(amps_t *amps, const char *bits, int count, double level, double quality, int negative); diff --git a/src/amps/main.c b/src/amps/main.c index 9cf18df..cc15575 100644 --- a/src/amps/main.c +++ b/src/amps/main.c @@ -44,7 +44,7 @@ int num_chan_type = 0; enum amps_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_PC_VC }; const char *flip_polarity = ""; -int ms_power = 4, dcc = 0, scc = 0, sid = 40, regh = 1, regr = 1, pureg = 1, pdreg = 1, locaid = -1, regincr = 300; +int ms_power = 4, dcc = 0, scc = 0, sid = 40, regh = 1, regr = 1, pureg = 1, pdreg = 1, locaid = -1, regincr = 300, bis = 0; void print_help(const char *arg0) { @@ -83,6 +83,9 @@ void print_help(const char *arg0) printf(" If 1, phone registers only if System ID matches (default = '%d')\n", regh); printf(" -S --sysinfo regr=0 | regr=1\n"); printf(" If 1, phone registers only if System ID is different (default = '%d')\n", regr); + printf(" -S --sysinfo bis=0 | bis=1\n"); + printf(" If 0, phone ignores BUSY/IDLE bit on FOCC (default = '%d')\n", bis); + printf(" If 1, be sure to have a round-trip delay (latency) not more than 5 ms\n"); printf("\nstation-id: Give 10 digit station-id, you don't need to enter it for every\n"); printf(" start of this program.\n"); } @@ -151,7 +154,7 @@ static int handle_options(int argc, char **argv) exit(0); } p++; - if (!strncasecmp(optarg, "sid=", 4)) { + if (!strncasecmp(optarg, "sid=", p - optarg)) { if (!strcasecmp(p, "list")) { list_stations(); exit(0); @@ -162,39 +165,42 @@ static int handle_options(int argc, char **argv) if (sid < 0) sid = 0; } else - if (!strncasecmp(optarg, "dcc=", 4)) { + if (!strncasecmp(optarg, "dcc=", p - optarg)) { dcc = atoi(p); if (dcc > 3) dcc = 3; if (dcc < 0) dcc = 0; } else - if (!strncasecmp(optarg, "scc=", 4)) { + if (!strncasecmp(optarg, "scc=", p - optarg)) { scc = atoi(p); if (scc > 2) scc = 2; if (scc < 0) scc = 0; } else - if (!strncasecmp(optarg, "regincr=", 4)) { + if (!strncasecmp(optarg, "regincr=", p - optarg)) { regincr = atoi(p); } else - if (!strncasecmp(optarg, "pureg=", 4)) { + if (!strncasecmp(optarg, "pureg=", p - optarg)) { pureg = atoi(p) & 1; } else - if (!strncasecmp(optarg, "pdreg=", 4)) { + if (!strncasecmp(optarg, "pdreg=", p - optarg)) { pdreg = atoi(p) & 1; } else - if (!strncasecmp(optarg, "locaid=", 4)) { + if (!strncasecmp(optarg, "locaid=", p - optarg)) { locaid = atoi(p); if (locaid > 4095) locaid = 4095; } else - if (!strncasecmp(optarg, "regh=", 4)) { + if (!strncasecmp(optarg, "regh=", p - optarg)) { regh = atoi(p) & 1; } else - if (!strncasecmp(optarg, "regr=", 4)) { + if (!strncasecmp(optarg, "regr=", p - optarg)) { regr = atoi(p) & 1; + } else + if (!strncasecmp(optarg, "bis=", p - optarg)) { + bis = atoi(p) & 1; } else { fprintf(stderr, "Given sysinfo parameter '%s' unknown, see help!\n", optarg); exit(0); @@ -259,6 +265,11 @@ int main(int argc, char *argv[]) exit(0); } + if (bis && latency > 5) { + fprintf(stdout, "If you use BUSY/IDLE bit, you need to lower the round-trip delay to 5 ms (--latenc 5).\n"); + exit(0); + } + if (!loopback) print_image(); sid_stations(sid); @@ -329,7 +340,7 @@ int main(int argc, char *argv[]) for (i = 0; i < num_kanal; i++) { amps_si si; - init_sysinfo(&si, ms_power, ms_power, dcc, sid >> 1, regh, regr, pureg, pdreg, locaid, regincr); + init_sysinfo(&si, ms_power, ms_power, dcc, sid >> 1, regh, regr, pureg, pdreg, locaid, regincr, bis); rc = amps_create(kanal[i], chan_type[i], sounddev[i], samplerate, cross_channels, rx_gain, do_pre_emphasis, do_de_emphasis, write_wave, read_wave, &si, sid, scc, polarity, loopback); if (rc < 0) { fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n"); diff --git a/src/amps/sysinfo.c b/src/amps/sysinfo.c index 204de08..e5664ca 100644 --- a/src/amps/sysinfo.c +++ b/src/amps/sysinfo.c @@ -41,7 +41,7 @@ static struct sysinfo_acc_attempt default_acc_attempt = { 10, }; -void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr) +void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis) { int i; @@ -56,7 +56,7 @@ void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, si->filler.cmac = cmac; si->filler.sdcc1 = 0; si->filler.sdcc2 = 0; - si->filler.wfom = 1; /* must be set to ignore B/I bit */ + si->filler.wfom = (bis) ? 0 : 1; /* must be set to ignore B/I bit */ /* Word 1 */ si->word1.sid1 = sid1; @@ -71,7 +71,7 @@ void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, si->word2.regr = regr; si->word2.dtx = 0; si->word2.n_1 = 20; - si->word2.rcf = 1; /* must be set to ignore B/I bit */ + si->word2.rcf = (bis) ? 0 : 1; /* must be set to ignore B/I bit */ si->word2.cpa = 1; /* must be set for combined CC+PC */ si->word2.cmax_1 = 20; @@ -99,7 +99,7 @@ void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, * So we don't set the B/I bit to busy on reception of message. * The access type message (including this 'bis') must also be included. */ - si->acc_type.bis = 0; /* must be clear to ignore B/I bit */ + si->acc_type.bis = bis; /* must be clear to ignore B/I bit */ si->acc_type.pci_home = 0; /* if set, bscap must allso be set */ si->acc_type.pci_roam = 0; /* if set, bscap must allso be set */ si->acc_type.bspc = 0; diff --git a/src/amps/sysinfo.h b/src/amps/sysinfo.h index 870218c..b786add 100644 --- a/src/amps/sysinfo.h +++ b/src/amps/sysinfo.h @@ -108,7 +108,7 @@ typedef struct system_information { int count; /* count message train */ } amps_si; -void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr); +void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis); void prepare_sysinfo(amps_si *si); uint64_t get_sysinfo(amps_si *si); |