Hi, All!
Кто там просил исходники на С для двухчастнотного анализа? Получите :) Железяка даже работала когда-то. Комментарии и замечания приветствуются.
=== main.c === /* * Title : Multi Frequency Tranceiver (1-bit verison) * Version : 0.43 * Last Update : 7 March 2003 * Target MCU : Atmel AVR AT90s2313 * XTAL : 8 MHz * Compiler : IAR Atmel AVR C/EC++ Compiler V2.26N/WIN * * Copyright (c) Jan 2003, Eugene Soloshenko snipped-for-privacy@mail.ru * All rights reserved. * * Description: * MF transceiver detects group of frequencies in the input signal and * returns their spectral power as a 2-byte numbers. At once transceiver can * analyse the following groups of frequencies: * a) AON (subscriber id, "2 from 6" protocol R1.5) * 700, 900, 1100, 1300, 1500, 1700 Hz * b) 425, 700, 1000, 2600 Hz * * For frequency detection is used 1-bit correlation (just a xor) between * input signal from comparator and reference frequency from table. */
#include <io2313.h>
#include <ina90.h>
#include "macros.h" #include "bit.h" #include "hardw.h"
/* * Global variables */
#define SAMPLE_CONST 443 // XTAL/(SAMPLE_CONST+1) = 8e6/444 = 18.018 kHz
uchar __flash copyright[]="(c) Eugene Soloshenko snipped-for-privacy@mal.ru"; uchar gen_time; // <signal duration> * 5mS uchar id; // id = fqCode + flag single/dual fq (bit7)
uint sp_pwr[6]; // spectral power for frequencies uchar *spwr_ptr; // ptr to spectral power array
uchar flags; // get_port() #define prev_STB 0 #define now_STB 1
#define CompNow 2 /* Sampled value from comparator */ #define NewCompSampl 3 /* flag to tell main that we've got new value*/
/* * Function prototypes */ void generate(void); void detect_AON (void); void detect_tone (void); uchar get_port (void);
/************************************************************************** * Interface section. Interface with external master **************************************************************************/
// RW_PIN logic #define WR 0 #define RD 1
// Commands from master - 4 commands implemented // // 00xx xxxx - GEN_AON // 01xx xxxx - GEN_TONE // 10xx xxxx - DET_AON // 11xx xxxx - DET_TONE // ||| | // ||`-----`--- parameters // ``---------- command type
#define GEN_AON 0x00 // 0b00000000 - generate AON "2 from 6" #define GEN_TONE 0x40 // 0b01000000 - generate single tone #define DET_AON 0x80 // 0b10000000 - detect AON "2 from 6" #define DET_TONE 0xC0 // 0b11000000 - detect single tone
#define CMD_MASK 0xC0 // 11000000b - parameters mask
/*************************************************************************** * Main ***************************************************************************/ __C_task void main (void) {
init_port(); /* set init directions & levels */
TCNT1H = TCNT1L = 0; OCR1 = SAMPLE_CONST;
SETBIT(TCCR1B,CTC1); // enable tmr clear on compare
/* Enable interrupt from tmr1_compare */ __enable_interrupt(); SETBIT(TIMSK,OCIE1A);
/* Start WDT */ #ifdef WDT_ON WDTCR = _WDT_REG; // enable WDT (see hardw.h) #endif
// on(BUSY); // busy now on(SMPL_TEST); // Main loop for (;;) {
uchar cmd; uchar tmp;
#ifdef WDT_ON __watchdog_reset(); #endif
tmp = cmd = get_port(); tmp &= CMD_MASK; // mask parameters to decode command // command in bits B7,B6
if (tmp == GEN_AON) {
id = cmd & 0x0F; // 00001111b params = 4 lower bits SETBIT(id,7); // flag dual-fq generation gen_time = get_port(); // get generation time generate();
} else if (tmp == GEN_TONE) {
id = cmd & 0x07; // 00000111b param = 3 lower bits gen_time = get_port(); // get generation time generate();
}else if (tmp == DET_AON) { detect_AON(); spwr_ptr = (uchar *)(sp_pwr); /* update ptr to spectral summ */ }
else if (tmp == DET_TONE) { detect_tone(); spwr_ptr = (uchar *)(sp_pwr); /* update ptr to spectral summ */ }
} // end for(;;) }
/**************************************************************************** * Generate section - not implemented ****************************************************************************/ void generate (void) {
}/**************************************************************************** * Detect section ****************************************************************************/
/* Number of sampled points. This value defines the length of the capture window. Twin = POINTS * 1/Fsample.
!!!NB no more than 170 points is allowed, cause array index has uchar-size so 1.5bytes/point => 170*1.5 = 255) */ #define POINTS 144 /* Twin = 8 mS for Fsample=18.018 kHz */
/* * Detect AON ("2 from 6") */ void detect_AON (void) {
/* Accum indexes. S- sin, C- cos */ enum {S_700, C_700, S_900, C_900, S_1100, C_1100, S_1300, C_1300, S_1500, C_1500, S_1700, C_1700};
/* * Table of frequencies being detected - sin/cos 700..1700 Hz * Fs = 18.018 kHz, 180 points */ static __flash uchar fq_tbl [] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xAF,0xAA,0xEA,0x8A,0x80,0xA8,0x1A,0x01, 0xA0,0x58,0x17,0x81,0x70,0x5F,0x07,0xE0,0x7E,0x17,0x81,0xF8,0x1E,0x81,0xE1, 0x5E,0x17,0x81,0x78,0x77,0x87,0x78,0x67,0x1E,0xE1,0xEE,0x1C,0xE3,0x8E,0x78, 0xE7,0x9C,0x71,0xC6,0x38,0xE3,0x8E,0x78,0xC6,0x9C,0x69,0x8E,0x98,0xC1,0x9C, 0x19,0x93,0x19,0x33,0x93,0x33,0x33,0x33,0x33,0x66,0x66,0x66,0x66,0x46,0x4C, 0x6C,0xC4,0xCD,0xCD,0x9C,0xDB,0xC9,0xBC,0x93,0xDB,0x2D,0xB2,0x93,0x69,0x24, 0x92,0x4B,0x2D,0xB6,0xDB,0x4D,0xB4,0xB3,0x4B,0x2D,0xB2,0xD2,0x2D,0x22,0xD0, 0x2B,0x44,0xB4,0x4B,0x54,0xAD,0x42,0xD4,0x2F,0x52,0xB5,0x0A,0xD4,0xAD,0x42, 0xD5,0x0F,0x50,0xFD,0x4F,0xD5,0xBF,0x5B,0xFF,0xAB,0xFA,0xAF,0xAA,0xAA,0xAA, 0xAA,0xA0,0x00,0x00,0x00,0x01,0x01,0x50,0x55,0x15,0x75,0x5F,0x57,0xF5,0xFE, 0x5F,0xA7,0xE8,0x7E,0x8F,0xA0,0xF8,0x1F,0x81,0xE8,0x7E,0x07,0xE1,0x7E,0x1E, 0xA1,0xE8,0x7E,0x87,0x88,0x78,0x87,0x98,0xE1,0x1E,0x11,0xE3,0x1C,0x71,0x87, 0x18,0x63,0x8E,0x39,0xC7,0x1C,0x71,0x87,0x39,0x63,0x96,0x71,0x67,0x3E,0x63, 0xE6,0x6C,0x66,0xCC,0x6C,0xCC,0xCC,0xCC,0xCC,0x99,0x99,0x99,0x99,0xB9,0xB3, 0x93,0x3B,0x32,0x33,0x63,0x26,0x36,0x43,0x6C,0x24,0xD2,0x4D,0x2C,0x96,0xDB, 0x6D,0xB4,0xD3,0x49,0x24,0xB2,0x4B,0x4C,0xB4,0xD2,0x4D,0x2D,0xD2,0xDD,0x2F, 0xD4,0xBB,0x4B,0xB4,0xAB,0x52,0xBD,0x2B,0xD0,0xAD,0x4A,0xF5,0x2B,0x52,0xBD, 0x2A,0xF0,0xAF,0x02,0xB0,0x2A,0x40,0xA4,0x00,0x50,0x05,0x50,0x55,0x55,0x55};
uchar sum[12]; /* accum array: sin700,cos700,sin900, ... */
uchar k; uchar i_t; /* index through fq table */ uint tbl_i; /* data from table for _all_ freqs being detected for current sample - 12 bits */
/* Clear accum */ k = 11; do { sum[k] = 0; } while (k-- != 0);
i_t = 0;
TCCR1B |= 1; // start tmr1 w/o prescaling CLEARBIT(flags,NewCompSampl);
/* Calculate correlation for current sample */ for (k = 0; k != POINTS; k++) {
/* wait for new sample from comparator */ while (!TESTBIT(flags,NewCompSampl)) ;
CLEARBIT(flags,NewCompSampl);
BYTE(tbl_i,WHI) = fq_tbl[i_t++]; BYTE(tbl_i,WLO) = fq_tbl[i_t];
if ( TESTBIT(flags,CompNow) ) { tbl_i = ~tbl_i; }
if ( TESTBIT(k,0) ) { /* for odd samples shift to left edge, even samples already at left edge */ i_t++; tbl_i<<=4; }
/* Proccess from left to right */ if ( TESTBIT(BYTE(tbl_i,WHI),7) ) sum[S_700]++;
if ( TESTBIT(BYTE(tbl_i,WHI),6) ) sum[C_700]++;
if ( TESTBIT(BYTE(tbl_i,WHI),5) ) sum[S_900]++;
if ( TESTBIT(BYTE(tbl_i,WHI),4) ) sum[C_900]++;
if ( TESTBIT(BYTE(tbl_i,WHI),3) ) sum[S_1100]++;
if ( TESTBIT(BYTE(tbl_i,WHI),2) ) sum[C_1100]++;
if ( TESTBIT(BYTE(tbl_i,WHI),1) ) sum[S_1300]++;
if ( TESTBIT(BYTE(tbl_i,WHI),0) ) sum[C_1300]++;
if ( TESTBIT(BYTE(tbl_i,WLO),7) ) sum[S_1500]++;
if ( TESTBIT(BYTE(tbl_i,WLO),6) ) sum[C_1500]++;
if ( TESTBIT(BYTE(tbl_i,WLO),5) ) sum[S_1700]++;
if ( TESTBIT(BYTE(tbl_i,WLO),4) ) sum[C_1700]++;
} /* end fq checking for current sample */
/* Normalize accumulators */ k = 11; do {
if (sum[k] < POINTS/2) sum[k]=~(sum[k]-POINTS/2); else sum[k] -= POINTS/2;
} while (k-- != 0);
/* Calculate spectral power */ for (k=0; k != 6; k++) { sp_pwr[k] = sum[k*2]*sum[k*2] + sum[k*2+1]*sum[k*2+1]; }
TCCR1B &= 0xF8; // 11111000b stop tmr1 }
/* * Detet tones (425, 700, 100, 2600 Hz) */ void detect_tone (void) {
/* Accum indexes. S- sin, C- cos */ enum {S_425, C_425, S_700, C_700, S_1000, C_1000, S_2600, C_2600 };
/* * Table of frequencies being detected - sin/cos 425, 700, 1000, 2600 * Fs = 18.018 kHz, 180 points */ static uchar __flash fq_tbl [] = {
0xFF,0xFF,0xFE,0xFE,0xFC,0xF8,0xF9,0xEB,0xEB,0xEA,0xE2,0xA0,0xA0,0x81,0x87, 0x87,0x86,0x86,0x84,0x8C,0x9D,0x9F,0x1F,0x1A,0x1A,0x18,0x39,0x39,0x33,0x33, 0x32,0x32,0x74,0x65,0x65,0x67,0x67,0x6E,0x6E,0x4C,0x4D,0x49,0x4B,0xCB,0xCA, 0xCA,0xD0,0xD1,0xD1,0xD3,0xD7,0xD6,0xF4,0xB4,0xB5,0xBD,0xBF,0xBF,0xAE,0xA8, 0xA8,0xA9,0xA9,0xAB,0x23,0x02,0x00,0x00,0x05,0x05,0x07,0x17,0x16,0x1C,0x1C, 0x5D,0x5D,0x5B,0x7A,0x7A,0x78,0x78,0x71,0x71,0x63,0xE2,0xE6,0xE4,0xE4,0xE5, 0xE5,0xCF,0xCE,0xCE,0xCC,0xC8,0x89,0x99,0x9B,0x9A,0x92,0x90,0x90,0xB1,0xB7, 0xB7,0x36,0x36,0x34,0x3C,0x2D,0x2F,0x2F,0x2A,0x2A,0x28,0x08,0x49,0x43,0x43, 0x42,0x42,0x44,0x54,0x55,0x57,0x57,0x5E,0xDE,0xFC,0xFD,0xF9,0xFB,0xFB,0xFA, 0xFA,0xE0,0xE1,0xA1,0xA3,0xA7,0xA6,0x86,0x84,0x85,0x8D,0x8F,0x8F,0x8E,0x18, 0x18,0x19,0x19,0x1B,0x13,0x32,0x30,0x30,0x35,0x75,0x77,0x67,0x66,0x6C,0x6C, 0x6D,0x6D,0x6B,0x4B,0x4A,0xC8,0xC8,0xC1,0xC1,0xD3,0xD2,0xD6,0xD4,0xD4,0xD5};
uchar sum[8]; /* accum array: sin425,cos425,sin700, ... */
uchar k; uchar i_t; /* index through fq table */ uchar tbl_i; /* data from table for _all_ freqs being detected for current sample - 8 bits */
/* Clear accum */ k = 7; do { sum[k] = 0; } while (k-- != 0);
i_t = 0;
TCCR1B |= 1; // start tmr1 w/o prescaling CLEARBIT(flags,NewCompSampl);
/* Calculate correlation for current sample */ for (k = 0; k != POINTS; k++) {
/* wait for new sample from comparator */ while (!TESTBIT(flags,NewCompSampl)) ;
CLEARBIT(flags,NewCompSampl);
tbl_i = fq_tbl[i_t++];
if ( TESTBIT(flags,CompNow) ) { tbl_i = ~tbl_i; }
/* Proccess from left to right */ if ( TESTBIT(tbl_i,7) ) sum[S_425]++;
if ( TESTBIT(tbl_i,6) ) sum[C_425]++;
if ( TESTBIT(tbl_i,5) ) sum[S_700]++;
if ( TESTBIT(tbl_i,4) ) sum[C_700]++;
if ( TESTBIT(tbl_i,3) ) sum[S_1000]++;
if ( TESTBIT(tbl_i,2) ) sum[C_1000]++;
if ( TESTBIT(tbl_i,1) ) sum[S_2600]++;
if ( TESTBIT(tbl_i,0) ) sum[C_2600]++;
} /* end fq checking for current sample */
/* Normalize accumulators */ k = 7; do {
if (sum[k] < POINTS/2) sum[k]=~(sum[k]-POINTS/2); else sum[k] -= POINTS/2;
} while (k-- != 0);
/* Calculate spectral power */ for (k=0; k != 4; k++) { sp_pwr[k] = sum[k*2]*sum[k*2] + sum[k*2+1]*sum[k*2+1]; }
TCCR1B &= 0xF8; // 11111000b stop tmr1
}/* * External interface * * Master: * - set STB = 0 * - set CS = 0 * - set RW_PIN = 0 (for write) RW_PIN = 1 (for read) * - check if slave (MFchip) availible (BUSY = 0) * Write: * - set data * - leading edge STB * Read: * - leading edge STB * - slave sets data and BUSY flag * - read data (slave hold data while STB is active) * * While master is reading (leading edge at RW_PIN = 1) - we sit in function * If master reads more than array sum[] size, then RAM after array will * be read. * Exit when command from master is reaceived (leading edge at RW_PIN = 0) */
uchar get_port (void) {
uchar res;
/* sample current STB level: now_STB = STB_PIN */ if ( signal(STB) ) { SETBIT(flags,now_STB); } else { CLEARBIT(flags,now_STB); }
wait_CS:
/* Data bus as input */ DDRB = _DIRB_IN; DDRD = _DIRD_Z; // off busy
while ( signal(CS) ) { ; // wait for CS == 0 #ifdef WDT_ON __watchdog_reset(); #endif }
DDRD = _DIRD_IN; // off busy off (BUSY); // tell to master that we are ready
// Wait STB leading edge and check CS do {
#ifdef WDT_ON __watchdog_reset(); #endif
if (signal(CS)) // CS==1 => urgent exit goto wait_CS;
// store prev state : prev_STB = now_STB if (TESTBIT(flags,now_STB)) { SETBIT(flags,prev_STB); } else { CLEARBIT(flags,prev_STB); }
/* sample current STB level: now_STB = STB_PIN */ if ( signal(STB) ) { SETBIT(flags,now_STB); } else { CLEARBIT(flags,now_STB); }
} while (!(TESTBIT(flags,now_STB) && !TESTBIT(flags,prev_STB))); // leading edge
// Switch RD - /WD ? if ( signal(RW) ) { // RD state
DATA_L_OUT &= 0x0F; // clr data bus DATA_H_OUT &= 0xF0; // clr data bus
DATA_L_OUT |= ((*spwr_ptr)<<4); // low nibble, 0 in unsed bit coz pullup off DATA_H_OUT |= ((*spwr_ptr)>>4); // high nibble
spwr_ptr++;
/* Data bus as output */ DDRB = _DIRB_OUT; DDRD = _DIRD_OUT; on(BUSY); // set BUSY flag
/* sample current STB level: now_STB = STB_PIN */ if ( signal(STB) ) { SETBIT(flags,now_STB); } else { CLEARBIT(flags,now_STB); }
// wait for STB falling and check CS, RW. Hold data, while STB active do {
#ifdef WDT_ON __watchdog_reset(); #endif
if ( signal(CS) || !signal(RW) ) // CS==1 || RW==0 (write) goto wait_CS; // urgent exit
// store prev state : prev_STB = now_STB if (TESTBIT(flags,now_STB)) { SETBIT(flags,prev_STB); } else { CLEARBIT(flags,prev_STB); }
/* sample current STB level: now_STB = STB_PIN */ if ( signal(STB) ) { SETBIT(flags,now_STB); } else { CLEARBIT(flags,now_STB); }
} while (!(!TESTBIT(flags,now_STB) && TESTBIT(flags,prev_STB))); // drop
goto wait_CS; // sit in function // switch port to input with first cmd after goto } else { // WR state res = ((DATA_H_IN)<<4); res |= ((DATA_L_IN)>>4); on(BUSY); // set BUSY flag return (res); }
}/* * Timer1 compare interrupt * Sampling frequency = 18.018 kHz (T = 55.5 uS ) */ #pragma vector = TIMER1_COMP1_vect __interrupt void TIMER1_COMP1_interrupt(void) {
/* sample comparator */ if ( signal(COMP) ) { SETBIT(flags,CompNow); } else { CLEARBIT(flags,CompNow); }
cpl(SMPL_TEST); // test signal
SETBIT(flags,NewCompSampl); // tell to main that we've got new sample }
=== main.c ===
wbr, eugene // solosh '\x40' mail.ru