summaryrefslogtreecommitdiff
path: root/tonezone.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-14 23:47:31 +0000
committerkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-14 23:47:31 +0000
commite82cf68ec969ba027f671b27261442b54b5f8737 (patch)
tree4a8a03d12bd400e69f53b7fce7f3075a41a407c2 /tonezone.c
parentef2eddaeb8ac4e25b283081911a36a642ce5f157 (diff)
(merging dtmf-twister branch plus a few fixes)
move DTMF/MF generation into tonezone.c (libtonezone) so that it can happen at runtime instead of compile time; this allows for DTMF/MF to be different on a zone-by-zone basis without requiring a recompile of Zaptel set DTMF 'twist' for Brazil (zone 'br') to 2dB git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3490 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'tonezone.c')
-rw-r--r--tonezone.c217
1 files changed, 160 insertions, 57 deletions
diff --git a/tonezone.c b/tonezone.c
index deb1ac1..413498f 100644
--- a/tonezone.c
+++ b/tonezone.c
@@ -29,6 +29,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
+
#include "tonezone.h"
#define DEFAULT_ZT_DEV "/dev/zap/ctl"
@@ -63,15 +64,15 @@ struct tone_zone *tone_zone_find_by_num(int id)
#define LEVEL -10
-static int build_tone(char *data, int size, struct tone_zone_sound *t, int *count)
+static int build_tone(void *data, int size, struct tone_zone_sound *t, int *count)
{
char *dup, *s;
struct zt_tone_def *td=NULL;
int firstnobang = -1;
int freq1, freq2, time;
- int used = 0;
int modulate = 0;
float gain;
+ int used = 0;
dup = strdup(t->data);
s = strtok(dup, ",");
while(s && strlen(s)) {
@@ -125,11 +126,11 @@ static int build_tone(char *data, int size, struct tone_zone_sound *t, int *coun
#if 0
printf("Using %d samples for %d and %d\n", time * 8, freq1, freq2);
#endif
- if (size < sizeof(struct zt_tone_def)) {
- fprintf(stderr, "Not enough space for samples\n");
+ if (size < sizeof(*td)) {
+ fprintf(stderr, "Not enough space for tones\n");
return -1;
}
- td = (struct zt_tone_def *)data;
+ td = data;
/* Bring it down -8 dbm */
gain = pow(10.0, (LEVEL - 3.14) / 20.0) * 65536.0 / 2.0;
@@ -144,9 +145,9 @@ static int build_tone(char *data, int size, struct tone_zone_sound *t, int *coun
td->modulate = modulate;
- data += (sizeof(struct zt_tone_def));
- used += (sizeof(struct zt_tone_def));
- size -= (sizeof(struct zt_tone_def));
+ data += sizeof(*td);
+ used += sizeof(*td);
+ size -= sizeof(*td);
td->tone = t->toneid;
if (time) {
/* We should move to the next tone */
@@ -157,7 +158,7 @@ static int build_tone(char *data, int size, struct tone_zone_sound *t, int *coun
td->next = *count;
td->samples = 8000;
}
- (*count)++;
+ *count += 1;
s = strtok(NULL, ",");
}
if (td && time) {
@@ -203,85 +204,187 @@ char *tone_zone_tone_name(int id)
}
#ifdef TONEZONE_DRIVER
-static void dump_tone_zone(void *data)
+static void dump_tone_zone(void *data, int size)
{
struct zt_tone_def_header *z;
struct zt_tone_def *td;
int x;
- int len=0;
+ int len = sizeof(*z);
+
z = data;
data += sizeof(*z);
printf("Header: %d tones, %d bytes of data, zone %d (%s)\n",
- z->count, z->size, z->zone, z->name);
- for (x=0;x < z->count; x++) {
+ z->count, size, z->zone, z->name);
+ for (x = 0; x < z->count; x++) {
td = data;
- printf("Tone Fragment %d: %d bytes, %s tone, next is %d, %d samples total\n",
- x, td->size, tone_name(td->tone), td->next, td->samples);
+ printf("Tone Fragment %d: tone is %d, next is %d, %d samples\n",
+ x, td->tone, td->next, td->samples);
data += sizeof(*td);
- data += td->size;
- len += td->size;
+ len += sizeof(*td);
}
printf("Total measured bytes of data: %d\n", len);
}
#endif
+/* Tone frequency tables */
+struct mf_tone {
+ int tone;
+ float f1; /* first freq */
+ float f2; /* second freq */
+};
+
+static struct mf_tone dtmf_dial[] = {
+ { ZT_TONE_DTMF_0, 941.0, 1336.0 },
+ { ZT_TONE_DTMF_1, 697.0, 1209.0 },
+ { ZT_TONE_DTMF_2, 697.0, 1336.0 },
+ { ZT_TONE_DTMF_3, 697.0, 1477.0 },
+ { ZT_TONE_DTMF_4, 770.0, 1209.0 },
+ { ZT_TONE_DTMF_5, 770.0, 1336.0 },
+ { ZT_TONE_DTMF_6, 770.0, 1477.0 },
+ { ZT_TONE_DTMF_7, 852.0, 1209.0 },
+ { ZT_TONE_DTMF_8, 852.0, 1336.0 },
+ { ZT_TONE_DTMF_9, 852.0, 1477.0 },
+ { ZT_TONE_DTMF_s, 941.0, 1209.0 },
+ { ZT_TONE_DTMF_p, 941.0, 1477.0 },
+ { ZT_TONE_DTMF_A, 697.0, 1633.0 },
+ { ZT_TONE_DTMF_B, 770.0, 1633.0 },
+ { ZT_TONE_DTMF_C, 852.0, 1633.0 },
+ { ZT_TONE_DTMF_D, 941.0, 1633.0 },
+ { 0, 0, 0 }
+};
+
+static struct mf_tone mf_dial[] = {
+ { ZT_TONE_MF_0, 1300.0, 1500.0 },
+ { ZT_TONE_MF_1, 700.0, 900.0 },
+ { ZT_TONE_MF_2, 700.0, 1100.0 },
+ { ZT_TONE_MF_3, 900.0, 1100.0 },
+ { ZT_TONE_MF_4, 700.0, 1300.0 },
+ { ZT_TONE_MF_5, 900.0, 1300.0 },
+ { ZT_TONE_MF_6, 1100.0, 1300.0 },
+ { ZT_TONE_MF_7, 700.0, 1500.0 },
+ { ZT_TONE_MF_8, 900.0, 1500.0 },
+ { ZT_TONE_MF_9, 1100.0, 1500.0 },
+ { ZT_TONE_MF_s, 1100.0, 1700.0 }, /* KP */
+ { ZT_TONE_MF_p, 1500.0, 1700.0 }, /* ST */
+ { ZT_TONE_MF_A, 900.0, 1700.0 }, /* ST' */
+ { ZT_TONE_MF_B, 1300.0, 1700.0 }, /* ST'' */
+ { ZT_TONE_MF_C, 700.0, 1700.0 }, /* ST''' */
+ { 0, 0, 0 }
+};
+
+static int build_mf_tones(void *data, int size, int *count, struct mf_tone *tone, int low_tone_level, int high_tone_level)
+{
+ struct zt_tone_def *td;
+ float gain;
+ int used = 0;
+
+ while (tone->tone) {
+ if (size < sizeof(*td)) {
+ fprintf(stderr, "Not enough space for samples\n");
+ return -1;
+ }
+ td = data;
+ data += sizeof(*td);
+ used += sizeof(*td);
+ size -= sizeof(*td);
+ td->tone = tone->tone;
+ *count += 1;
+
+ /* Bring it down 6 dBm */
+ gain = pow(10.0, (low_tone_level - 3.14) / 20.0) * 65536.0 / 2.0;
+ td->fac1 = 2.0 * cos(2.0 * M_PI * (tone->f1 / 8000.0)) * 32768.0;
+ td->init_v2_1 = sin(-4.0 * M_PI * (tone->f1 / 8000.0)) * gain;
+ td->init_v3_1 = sin(-2.0 * M_PI * (tone->f1 / 8000.0)) * gain;
+
+ gain = pow(10.0, (high_tone_level - 3.14) / 20.0) * 65536.0 / 2.0;
+ td->fac2 = 2.0 * cos(2.0 * M_PI * (tone->f2 / 8000.0)) * 32768.0;
+ td->init_v2_2 = sin(-4.0 * M_PI * (tone->f2 / 8000.0)) * gain;
+ td->init_v3_2 = sin(-2.0 * M_PI * (tone->f2 / 8000.0)) * gain;
+
+ tone++;
+ }
+
+ return used;
+}
+
int tone_zone_register_zone(int fd, struct tone_zone *z)
{
char buf[MAX_SIZE];
int res;
- int count=0;
+ int count = 0;
int x;
- int used = 0;
- int iopenedit = 0;
int space = MAX_SIZE;
- char *ptr = buf;
+ void *ptr = buf;
+ int iopenedit = 1;
struct zt_tone_def_header *h;
- if (fd < 0) {
- fd = open(DEFAULT_ZT_DEV, O_RDWR);
- iopenedit=1;
- if (fd < 0) {
- fprintf(stderr, "Unable to open %s and fd not provided\n", DEFAULT_ZT_DEV);
- return -1;
- }
- }
- h = (struct zt_tone_def_header *)ptr;
- ptr += sizeof(struct zt_tone_def_header);
- space -= sizeof(struct zt_tone_def_header);
- used += sizeof(struct zt_tone_def_header);
- /*
- * Fill in ring cadence
- */
- for (x=0;x<ZT_MAX_CADENCE;x++)
+
+ h = ptr;
+ ptr += sizeof(*h);
+ space -= sizeof(*h);
+ h->zone = z->zone;
+
+ strncpy(h->name, z->description, sizeof(h->name) - 1);
+
+ for (x = 0; x < ZT_MAX_CADENCE; x++)
h->ringcadence[x] = z->ringcadence[x];
- /* Put in an appropriate method for a kernel ioctl */
- for (x=0;x<ZT_TONE_MAX;x++) {
- if (strlen(z->tones[x].data)) {
- /* It's a real tone */
+
+ for (x = 0; x < ZT_TONE_MAX; x++) {
+ if (!strlen(z->tones[x].data))
+ continue;
+
#if 0
- printf("Tone: %d, string: %s\n", z->tones[x].toneid, z->tones[x].data);
+ printf("Tone: %d, string: %s\n", z->tones[x].toneid, z->tones[x].data);
#endif
- res = build_tone(ptr, space, &z->tones[x], &count);
- if (res < 0) {
- fprintf(stderr, "Tone not built.\n");
- if (iopenedit)
- close(fd);
- return -1;
- }
- ptr += res;
- used += res;
- space -= res;
+ if ((res = build_tone(ptr, space, &z->tones[x], &count)) < 0) {
+ fprintf(stderr, "Tone %d not built.\n", x);
+ return -1;
}
+ ptr += res;
+ space -= res;
}
+
+ if ((res = build_mf_tones(ptr, space, &count, dtmf_dial, z->dtmf_low_level, z->dtmf_high_level)) < 0) {
+ fprintf(stderr, "Could not build DTMF tones.\n");
+ return -1;
+ }
+ ptr += res;
+ space -= res;
+
+ if ((res = build_mf_tones(ptr, space, &count, mf_dial, z->mf_level, z->mf_level)) < 0) {
+ fprintf(stderr, "Could not build MF tones.\n");
+ return -1;
+ }
+ ptr += res;
+ space -= res;
+
h->count = count;
- h->zone = z->zone;
- strncpy(h->name, z->description, sizeof(h->name));
+
+ if (fd < 0) {
+ if ((fd = open(DEFAULT_ZT_DEV, O_RDWR)) < 0) {
+ fprintf(stderr, "Unable to open %s and fd not provided\n", DEFAULT_ZT_DEV);
+ return -1;
+ }
+ iopenedit = 1;
+ }
+
x = z->zone;
- ioctl(fd, ZT_FREEZONE, &x);
- res = ioctl(fd, ZT_LOADZONE, h);
- if (res)
+ if ((res = ioctl(fd, ZT_FREEZONE, &x))) {
+ fprintf(stderr, "ioctl(ZT_FREEZONE) failed: %s\n", strerror(errno));
+ return res;
+ }
+
+#if defined(TONEZONE_DRIVER)
+ dump_tone_zone(h, MAX_SIZE - space);
+#endif
+
+ if ((res = ioctl(fd, ZT_LOADZONE, h))) {
fprintf(stderr, "ioctl(ZT_LOADZONE) failed: %s\n", strerror(errno));
+ return res;
+ }
+
if (iopenedit)
close(fd);
+
return res;
}