2
ACfax - Fax reception with X11-interface for amateur radio
3
Copyright (C) 1995-1998 Andreas Czechanowski, DL4SDC
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software Foundation,
17
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
andreas.czechanowski@ins.uni-stuttgart.de
23
* sblaster.c - this file should contain all hardware-dependent functions
24
* on top of mod_demod.c for the SoundBlaster under linux.
30
#include <sys/ioctl.h>
31
#include <sys/soundcard.h>
32
#include "mod_demod.h"
49
/* this constants should go to a configuration file in future.... */
50
unsigned fm_smplf = (unsigned)(FM_SMPLF * 65536);
51
unsigned am_smplf = (unsigned)(AM_SMPLF * 65536);
53
static void set_speed(int);
55
/* initialize the interface: open it, set it to mono, 8bits per sample,
56
* and allocate space for the input- and output-buffers of the modem-
57
* routines. return a pointer to the decoded data and the number of
58
* values per call to do_receive.
60
void interface_init(char **dta_return, int *cnt_return)
68
int recsrc = SOUND_MASK_LINE;
70
static int inited = 0;
72
/* already initialized ? return values although... */
75
*cnt_return = decsize;
79
fprintf(stderr, "opening and initializing sound-interface\n");
80
if ((afd = open(DSPDEV, O_RDWR, 0666)) < 0) {
86
if ((mfd = open(MIXDEV, O_RDWR, 0666)) < 0) {
91
linevol += linevol << 8;
93
mastervol += mastervol << 8;
94
if ((ioctl(mfd, SOUND_MIXER_WRITE_LINE, &linevol) < 0) ||
95
(ioctl(mfd, SOUND_MIXER_WRITE_VOLUME, &mastervol) < 0) ||
96
(ioctl(mfd, SOUND_MIXER_WRITE_RECSRC, &recsrc) < 0)) {
97
perror("mixer_ioctl");
102
if ((ioctl(afd, SNDCTL_DSP_SPEED, &speed) < 0) ||
103
(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &bits) < 0) ||
104
(ioctl(afd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
105
(ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blsize) < 0)) {
109
decsize = blsize / 2;
110
/* set up defaults for the modem */
114
set_modem_param (afilter, amaxval, adevi);
115
if (!(decptr = malloc((decsize))) ||
116
!(smplptr = malloc(blsize))) {
117
perror("setup_buffers");
120
printf("block size is %d bytes\n", blsize);
121
*dta_return = decptr;
122
*cnt_return = decsize;
127
/* stop the interface, don't let it overrun by no more reading/writing */
128
void interface_stop(void)
130
if (ioctl(afd, SNDCTL_DSP_RESET, NULL) < 0) {
131
perror("interface_stop: cannot reset pcm");
135
/* set up the desired mode, the decoded value range and the deviation for
136
* FM. Return the number of demodulated sample-points per second (for APT)
138
void setup_mode(int mode, int maxval, int devi, unsigned *smplf)
144
/* be sure interface is initialized */
145
interface_init(&dummy1, &dummy2);
147
if ((id = (mode & MOD_BITS))) {
157
fprintf(stderr, "setting demodulator mode to 0x%04x\n", amode);
159
/* range checking for afilter, adevi and amaxval is done in mod_demod.c */
160
if ((id = mode & FIL_MASK)) {
162
fprintf(stderr, "setting filter selection to 0x%04x\n", afilter);
166
fprintf(stderr, "setting deviation to %d\n", adevi);
170
fprintf(stderr, "setting max.demod.value to %d\n", amaxval);
172
if ((mode & FIL_MASK) | (devi) | (maxval)) {
173
set_modem_param (afilter, amaxval, adevi);
175
/* return the number of samples per second (16 bits int, 16 bits frac) */
188
/* receive the signal, demodulate it, ant put the demodulated values
189
* into an array starting at decptr with decsize bytes. (1 byte / value)
191
void do_receive(void)
197
cnt = read(afd, smplptr, blsize);
199
perror("do_receive");
205
am_demod(smplptr, cnt, decptr);
208
fm_demod(smplptr, cnt, decptr);
213
/* determine the signal level and put it into rx_level (0..255) */
216
for (i = 0; i < blsize / 4; i++)
218
sample = smplptr[i] & 0xff;
219
if (sample > hi) hi = sample;
220
if (sample < lo) lo = sample;
225
/* modulate the sample-values from decptr into smplptr, and transmit them
226
* over the interface. The number of input-values is always decsize.
228
void do_transmit(void)
234
fm_modulate(decptr, decsize, smplptr);
236
am_modulate(decptr, decsize, smplptr);
240
cnt = write(afd, smplptr, blsize);
242
perror("do_transmit");
248
/* check for signal level, return a value between 0 and 256 */
249
int signal_level(void)
254
if (read(afd, buf, 512) != 512) {
255
perror("signal_level: cannot get samples");
257
if (ioctl(afd, SNDCTL_DSP_SYNC, NULL) < 0) {
258
perror("signal_level: cannot reset pcm");
262
for (i=0; i<512; i++) {
270
/* just assign new value to either the AM or FM sample-frequency,
271
and hold values permanently until next change
273
void tune_frequency(unsigned freq)
285
/* set a new sample-rate for the DSP-device. We need to restart input
286
in order to do so, because Linux does not update the SB-registers
287
when sending the command, but only on start of input/output
289
static void set_speed(int speed)
291
if (ioctl(afd, SNDCTL_DSP_SPEED, &speed) < 0) {
292
perror("set_speed: cannot set new sample-rate");
294
fprintf(stderr,"speed set to %d\n", speed);
295
if (ioctl(afd, SNDCTL_DSP_SYNC, NULL) < 0) {
296
perror("set_speed: cannot reset pcm");