mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
Line.cpp
- Committer:
- okini3939
- Date:
- 2011-01-21
- Revision:
- 6:bd62b12de751
- Parent:
- 5:30e2847d241b
File content as of revision 6:bd62b12de751:
/** @file Line.cpp * @brief Line Controller (mbed Phone Platform) */ #include "Line.h" #define RING_ON FREQ #define RING_OFF (FREQ * 3) #define RING_PULSE (FREQ / 16) #define TONE_DT (FREQ / 400) #define TONE_RBT_ON FREQ #define TONE_RBT_OFF (FREQ * 3) #define TONE_BT_ON (FREQ / 2) #define TONE_BT_OFF FREQ #define HOOK_TIME FREQ #define DIAL_TIME (FREQ / 2) const unsigned short tonetable[TONE_DT] = { 0x7fff, 0x98f4, 0xaf78, 0xc156, 0xcccf, 0xd0c3, 0xcccf, 0xc156, 0xaf78, 0x98f4, 0x7fff, 0x6709, 0x5085, 0x3ea7, 0x332e, 0x2f3a, 0x332e, 0x3ea7, 0x5085, 0x6709 }; Line::Line (PinName p_line, PinName p_xline, PinName p_hook, AnalogOut p_dac) : line(p_line), xline(p_xline), hook(p_hook), dac(p_dac), dial(DIAL_SIZE) { hook.mode(PullUp); mode = ModeOff; status = StatusOk; dialtimer = 0; dialcount = 0; hooktimer = 0; tonecount = 0; hooktimer2 = 0; hook_last = hook; } /** * @brief 8KHz interrupt */ void Line::intr () { switch (mode) { case ModeRing: ring(); break; case ModeDT: tone(DialTone); break; case ModeRBT: tone(RingBackTone); break; case ModeBT: tone(BusyTone); break; } if (hook) { // off hook if (hooktimer) hooktimer --; if (! hook_last && (dialcount > 0 || hooktimer2 >= DIAL_TIME)) { // dial trigger dialtimer = DIAL_TIME; dialcount ++; hooktimer2 = 0; } } else { // on hook hooktimer = HOOK_TIME; hooktimer2 ++; } hook_last = hook; if (dialtimer) { dialtimer --; if (dialtimer == 0 && dialcount && ! hook) { // dial detected dial.put(dialcount); dialcount = 0; } } else { dialcount = 0; } } void Line::poll () { } /** * @brief change mode * @param newmode mode of line * @retval 0 ok */ int Line::enter (enum Mode newmode) { // cleanup switch (mode) { case ModeRing: case ModeOff: power(1); break; case ModeDT: case ModeRBT: case ModeBT: dac.write_u16(0x7fff); break; } mode = newmode; switch (mode) { case ModeReady: // ready power(1); status = StatusOk; break; case ModeDT: case ModeRBT: case ModeBT: // tone tonecount = 0; status = StatusOk; break; case ModeOff: // suspend power(0); status = StatusOk; break; default: status = StatusOk; break; } return 0; } /** * @brief return status * @param type Type of status * @return status */ int Line::scan (enum Scan type) { switch (type) { case ScanMode: return (int)mode; case ScanStatus: return (int)status; case ScanHook: return hooktimer ? HookOn : HookOff; case ScanDial: char c; if (! dial.get(c)) { return c; } break; } return -1; } /** * @brief power of line * @param flg 0:off, 1:on(positive), -1:on(negative) */ void Line::power (int flg) { if (flg > 0) { xline = 0; wait_ms(1); line = 1; } else if (flg < 0) { line = 0; wait_ms(1); xline = 1; } else { line = 0; xline = 0; } } /// ring void Line::ring () { if (hook && tonecount < RING_ON) { // off hook switch (tonecount % RING_PULSE) { case 0: Line::power(0); break; case RING_PULSE / 10: Line::power(-1); break; case RING_PULSE / 2: Line::power(0); break; case RING_PULSE / 2 + RING_PULSE / 10: Line::power(1); break; } } tonecount ++; if (tonecount >= RING_OFF) tonecount = 0; } /// tone void Line::tone (enum Tone type) { if (! hook && ( type == DialTone || (type == RingBackTone && tonecount < TONE_RBT_ON && (tonecount % RING_PULSE) < (RING_PULSE / 2)) || (type == BusyTone && tonecount < TONE_BT_ON) ) ) { // on hook dac.write_u16(tonetable[tonecount % TONE_DT]); } else { // off hook dac.write_u16(0x7fff); } tonecount ++; if ( (type == DialTone && tonecount >= TONE_DT) || (type == RingBackTone && tonecount >= TONE_RBT_OFF) || (type == BusyTone && tonecount >= TONE_BT_OFF) ) { tonecount = 0; } }