aboutsummaryrefslogtreecommitdiffstats
path: root/lm.h
blob: 1f68f17f05333966bc46c6a570df32a49fe9e019 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#pragma once

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>

#include "dsp.h"

#define LM_VERSION "0.2.5"

/* bit fifo */

struct sm_fifo {
    unsigned char *sptr, *wptr, *rptr, *eptr;
    int size, max_size;
};

void sm_flush(struct sm_fifo *f);
int sm_size(struct sm_fifo *f);
void sm_put_bit(struct sm_fifo *f, int v);
void sm_put_bits(struct sm_fifo *f, int v, int n);
int sm_get_bit(struct sm_fifo *f);
int sm_get_bits(struct sm_fifo *f, int n);
void sm_init_fifo(struct sm_fifo *f, u8 *buf, int size);

/* bit I/O for data pumps */
typedef void (*put_bit_func)(void *opaque, int bit);
typedef int (*get_bit_func)(void *opaque);

/* timer */
struct sm_timer {
    long timeout;
};

int sm_time(void);
void sm_set_timer(struct sm_timer *t, int delay);
int sm_check_timer(struct sm_timer *t);

/* debug */
extern int lm_debug;
extern char *sm_states_str[];

/* protocol description */

#include "dtmf.h"
#include "fsk.h"
#include "v21.h"
#include "v22.h"
#include "v23.h"
#include "v8.h"
#include "v34.h"

/* modem state */
#define SM_FIFO_SIZE 4096

struct sm_state {
    /* pretty name of the modem (to debug) */
    char name[16];

    struct sm_hw_info *hw;
    struct lm_interface_state *hw_state;

    /* bytes to be transmitted */
    struct sm_fifo tx_fifo;
    u8 tx_fifo_buf[SM_FIFO_SIZE];

    /* received chars */
    struct sm_fifo rx_fifo;
    u8 rx_fifo_buf[SM_FIFO_SIZE];

    /* true if we are the caller */
    int calling;
    /* phone number to call */
    char call_num[64];
    int pulse_dial; /* TRUE if we must use pulse dialing */

    /* dialing */
    struct sm_timer dtmf_timer;
    DTMF_mod_state dtmf_tx;
    int dtmf_ptr, dtmf_len;   /* pointer in call_num */

    /* dtmf receive: for testing (or voice mode in the future) */
    struct sm_timer ring_timer;
    DTMF_demod_state dtmf_rx;

    /* modulation state */
    union {
        V8State v8_state;
        V21State v21_state;
        V23State v23_state;
    } u;

    /* serial state */
    int serial_data_bits; /* 5 to 8 */
    int serial_parity, serial_use_parity;
    int serial_wordsize;

    unsigned int serial_buf;
    int serial_cnt;
    
    unsigned int serial_tx_buf;
    int serial_tx_cnt;

    /* main modem state */
    int state;
    int debug_laststate;
    int hangup_request;
    unsigned int time; /* current time (in samples) */

    /* config */
    struct LinModemConfig *lm_config;
};

/* linmodem configuration registers */
typedef struct LinModemConfig {
    int pulse_dial;   /* default dial type */
    int dtmf_level;   /* in dB */
    int dtmf_digit_length; /* in ms */
    int dtmf_pause_length; /* in ms */
    int available_modulations; /* mask of available modulations */
} LinModemConfig;

/* abstract line interface driver */
struct lm_interface_state {
    struct sm_state *sm;
    int handle;
};

/* modem hardware interface abstraction */
/* XXX: must be slightly modified for kernel mode operation */
struct sm_hw_info {
    int (*open)(struct lm_interface_state *s);
    void (*close)(struct lm_interface_state *s);

    /* off hook or on hook modem */
    void (*set_offhook)(struct lm_interface_state *s, int v);

    /* when the ring is enabled, an event E_RING is sent to the
       process if a ring occured */
    void (*set_ring)(struct lm_interface_state *s, int v);

    /* the main modem loop is here */
    void (*main_loop)(struct lm_interface_state *s);
};

/* general state of the modem */

enum {
#define TAG(s) s,
#include "lmstates.h"
};

void lm_init(struct sm_state *sm, struct sm_hw_info *hw, const char *name);

/* main modem process */
void sm_process(struct sm_state *sm, s16 *output, s16 *input, int nb_samples);

int lm_start_dial(struct sm_state *s, int pulse, const char *number);
int lm_start_receive(struct sm_state *s);
int lm_hangup(struct sm_state *s);

enum lm_get_state_val {
    LM_STATE_IDLE,
    LM_STATE_CONNECTING,
    LM_STATE_CONNECTED,
};

enum lm_get_state_val lm_get_state(struct sm_state *s);

/* lmsim.c */

void line_simulate(void);

struct LineModelState;

struct LineModelState *line_model_init(void);
void line_model(struct LineModelState *s, 
                s16 *output1, const s16 *input1,
                s16 *output2, const s16 *input2,
                int nb_samples);

/* lmreal.c */

void real_test(int calling);

/* lmsoundcard.c */
void soundcard_modem(void);

/* serial.c */

void serial_init(struct sm_state *s, int data_bits, int parity);
int serial_get_bit(void *opaque);
void serial_put_bit(void *opaque, int bit);

/* atparser.c */

enum lm_at_state_type {
    AT_MODE_COMMAND,
    AT_MODE_DIALING,
    AT_MODE_CONNECTED,
};

struct lm_at_state {
    char at_line[256];
    int at_line_ptr;
    int at_state; 
    struct sm_state *sm; /* corresponding modem state */
};

void lm_at_parser_init(struct lm_at_state *s, struct sm_state *sm);
void lm_at_parser(struct lm_at_state *s);

#include "display.h"