📄 phonerec.c
字号:
/* [KSC4]-------------------------------------------------------------------[] * * PHONEREC.C - AVR Phone Recorder and Telephony Platform, version 1.0 * Written by AT3344 * * Portability: Tested with avr-gcc 3.4.3 and avr-libc 1.2.3 with an ATmega32 * ------------ device. * * []-----------------------------------------------------------------------[] */#ifndef __AVR_ATmega32__#error Hey, this code was only tested in an ATmega32#endif#include <avr/io.h>#include <avr/sleep.h>#include <avr/signal.h>#include <avr/pgmspace.h>#include <avr/interrupt.h>#include "commands.h"#define F_CPU 11059200L#include <avr/delay.h>/* ---------------- Compilation/Program Configuratio Options -------------- *//* If defined, LCD support and related features will be compiled in */#define HAVE_LCD 1#ifdef HAVE_LCD#include "lcd.h"#endif // HAVE_LCD// --- Hardware hookup /* Where the Request to Send pin is connected to */#define RTS_DDR DDRD#define RTS_PORT PORTD#define RTS_BIT PD5/* Where the hook relay is connected to */#define HOOK_DDR DDRB#define HOOK_PORT PORTB#define HOOK_BIT PB1#ifdef HAVE_LCD/* Where the LCD backlight is connected to */#define LCD_BACKLIGHT_DDR DDRC#define LCD_BACKLIGHT_PORT PORTC#define LCD_BACKLIGHT_BIT PC4#endif // HAVE_LCD/* If defined, it will compile the Goertzel algorithm stuff for DTMF detection */#define HAVE_GOERTZEL #ifdef HAVE_GOERTZEL#include "goertzel.h"#endif // HAVE_GOERTZEL/* If defined, the MMC support code will be compiled in */#define HAVE_MMC/* If defined, we will use ADPCM compression *//* WARNING: while most of the code is there, it is not working as of yet! *///#define USE_ADPCM_COMPRESSION#define USE_PROGMEM_CONSTANTS#define ADPCM_USES_LONGS#ifdef USE_PROGMEM_CONSTANTS#define _PROGMEM PROGMEM#else#define _PROGMEM#endif/* If defined, simultaneous record and playback will be allowed. If not, recording has priority over playback; in other words, when recording starts because of an incoming or outgoing call, playback is automatically cancelled. */#define ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK/* If defined, instead of the serial audio we will transmit the final value of TCNT0 at the end of the process_sample function, useful for analysing running time *///#define DEBUG_TIMING/* --------------------------- Macro-Defined Constants -------------------- */#define ADC_CHANNELS 8// These must be powers of 2!!! (because We use bitwise ANDs to wrap them)#define MAXTXFIFOLENGTH 16#define MAXRXFIFOLENGTH 8#define TRUE 1#define FALSE 0#define MAXDTMFSTRINGLENGTH 16#define MAXVISIBLEDTMFSTRINGLENGTH 16#define STEADY_COUNT 7#define MMC_CLUSTER_BITSHIFT 4#define MMC_CLUSTER_SIZE (1<<MMC_CLUSTER_BITSHIFT)#define MMC_CLUSTER_SIZE_MASK (MMC_CLUSTER_SIZE-1)#define MMC_BLOCK_SIZE_BITSHIFT 9#define MMC_BLOCK_SIZE (1<<MMC_BLOCK_SIZE_BITSHIFT)#define MMC_GO_IDLE_STATE 0#define MMC_SEND_OP_COND 1#define MMC_SEND_CSD 9#define MMC_SEND_CID 10 #define MMC_GO_INACTIVE_STATE 15#define MMC_SET_BLOCKLEN 16#define MMC_READ_SINGLE_BLOCK 17#define MMC_WRITE_BLOCK 24#define MMC_CRC_ON_OFF 59#define MMC_STARTBLOCK_READ 0xFE#define MMC_STARTBLOCK_WRITE 0xFE#define MMC_DR_MASK 0x1F#define MMC_DR_ACCEPT 0x05/* Audio statuses */#define AS_PLAYBACK_IN_PROGRESS 1#define AS_RECORDING_IN_PROGRESS 2#define AS_PLAYBACK_SHUTTING_DOWN 4#define AS_RECORDING_SHUTTING_DOWN 8#define DEFERRED_INDEX_WRITE 0x80/* --------------------------- Macro-Defined Functions -------------------- */#define nop() asm __volatile__("nop")/* ---------------------- Global Variables and Declarations --------------- */unsigned char txfifo[MAXTXFIFOLENGTH];volatile unsigned char fifo_head,fifo_tail;unsigned char rxfifo[MAXRXFIFOLENGTH];volatile unsigned char rxhead,rxtail;// The current sample, in two formats -- each convenient for a purpose// As signed 16 bit, for Goertzel algorithmvolatile short sample16; // As unsigned 8 bit, for playback and DTMF detectionvolatile unsigned char sample8; unsigned short count=AUDIO_BLOCK_LENGTH;// ADPCM Compression tables and variables#ifdef USE_ADPCM_COMPRESSION// This is the main ADPCM logarithmic quantization tableshort stepsizeTable[89] _PROGMEM = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767};// This is ADPCM's indexing offset tablechar indexTable[16] _PROGMEM = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8,};// ADPCM State#ifdef ADPCM_USES_LONGSlong inpred;char idx;unsigned char pending;#elseshort inpred;char idx;unsigned char pending;#endif // USE_LONGS_ON_ADPCM#endif // USE_ADPCM_COMPRESSIONenum hook_status_t { HookUnknown, OnHook, OffHook, Disconnected};#ifdef HAVE_LCD// 1234567890123456char PROGMEM on_hook_msg[]="IDLE %h:%m:%s";char PROGMEM off_hook_msg[]="IN USE %T%t";char PROGMEM disconn_msg[]="DISCONNECTED ";char PROGMEM ring_number_msg[]="RING #%r %T%t";char PROGMEM incoming_call_msg[]="INCOMING ";char PROGMEM tens[]="00000000001111111111222222222233333333334444444444" "55555555556666666666777777777788888888889999999999";prog_char *main_msg;unsigned char msg_index;#endif // HAVE_LCDunsigned char PROGMEM wav880[]={ 0x80,0xAD,0xC6,0xBE,0x9A,0x6A,0x43,0x39,0x4F,0x00};const prog_char *wavp,*wavp0;unsigned char wav_cnt,wav_rep,wav_mask,wav_rep0;volatile unsigned char steady;volatile enum hook_status_t last_hook,last_reported_hook;volatile unsigned char ring_count;volatile unsigned char has_sample;unsigned char last_pwm=0;unsigned char age=0;unsigned char ring_age=255;static unsigned char digit_age;#ifdef HAVE_LCDunsigned char l1;unsigned char gchrs[4],gchrs_index;#endif // HAVE_LCDunsigned short macroframe;unsigned char microframe;volatile unsigned char now_hour,now_min,now_sec;volatile unsigned char now_day=1,now_month=1,now_year;unsigned char PROGMEM mdays[]={ 31,28,31,30,31,30,31,31,30,31,30,31};unsigned char timer_hour,timer_min,timer_sec;enum timer_status_t { TimerStopped, TimerRunning} timer_status;enum call_status_t { CallIdle, CallIncoming, CallOutgoing} call_status=CallIdle;char dtmf_string[MAXDTMFSTRINGLENGTH];unsigned char dtmf_msg_pos,dtmf_string_length;unsigned char dialing_digits;char dtmf_digit;unsigned char ringlike,last_ringdet,ringdet_his,ringdet_los,ringdet_mids;unsigned char ringdet_quell;unsigned char cmd_cnt,pending_cmd;unsigned char monitor_mode;unsigned char gci;unsigned char kbd_read_state;unsigned char kbd_key,kbd_has_key,kbd_last_key;unsigned char PROGMEM kbd_tbl[]="RDEEUUULLLL";#ifdef HAVE_MMCunsigned char spi_buf[8];unsigned char spi_buf_tail,spi_buf_len,spi_ff;unsigned char spi_has_reply,spi_reply,spi_autofinish;unsigned char mmc_csd_index;unsigned char mmc_init_state=6,mmc_retry;unsigned char mmc_read_csd_state;unsigned short mmc_last_cluster;unsigned char mmc_psn[4];#define MAXCALLS 230#define MAGIC1 0x4A55#define MAGIC2 0x4D45struct mmc_index_t { unsigned short magic1; unsigned char mmc_psn[4]; unsigned short first_cluster; unsigned short last_cluster; unsigned short free; unsigned char first_call; unsigned char last_call; unsigned char reserved1[12]; unsigned short start[MAXCALLS]; unsigned char reserved2[510-26-2*MAXCALLS]; unsigned short magic2;} mmc_index;unsigned char *mmc_ptr;unsigned short mmc_ptr_count;unsigned char mmc_read_index_state;unsigned char mmc_read_state;unsigned char mmc_write_index_state;unsigned char mmc_write_state;unsigned char has_index,has_index_count;unsigned char buffer_a[512],buffer_b[512];unsigned short mmc_write_cluster,mmc_read_cluster,mmc_read_stop_at;unsigned char mmc_write_cluster_sector,mmc_read_cluster_sector;unsigned char mmc_write_buf_state,mmc_read_buf_state;unsigned char audio_status;unsigned char *audio_buf,*io_buf;unsigned short audio_cnt;unsigned char current_playback_call;unsigned char call_number[MAXDTMFSTRINGLENGTH];unsigned char call_year,call_month,call_day,call_hour,call_min,call_sec;unsigned char call_number_already_copied;#endif // HAVE_MMC#ifdef DO_HEXDUMPunsigned short hexdump_count;unsigned char *hexdump_ptr;#endif // DO_HEXDUMP//#define SHOW_DEBUG_COUNT#ifdef SHOW_DEBUG_COUNTunsigned short dcnt;#define set_dcnt(x) (dcnt=(x))#else#define set_dcnt(x)#endif // SHOW_DEBUG_COUNT/* -------------------------- Function Prototypes ------------------------- */unsigned char inline has_rx_data(void);unsigned char recv(void);void inline xmit(unsigned char c);void inline do_xmit(void);void process_sample(void);void update_hook_status(enum hook_status_t hook);void lcd_timer_print(void);void dtmf_string_clear(void);void dtmf_string_putc(char c);void inline call_timer_reset(void);void inline call_timer_stop(void);void copy_call_number(void);unsigned char get_int2(char *p);void u8to2d(unsigned char val);void inline spi_start_xmit(void);void inline spi_next_xmit(void);void inline spi_buf_reset(void);void inline spi_buf_putc(unsigned char c);void inline spi_get_next(void);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -