mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
Diff: Line.cpp
- Revision:
- 1:0f82c574096f
- Parent:
- 0:f18953137cb4
- Child:
- 2:e37117117e79
--- a/Line.cpp Mon Dec 20 22:55:29 2010 +0000 +++ b/Line.cpp Sun Dec 26 15:49:07 2010 +0000 @@ -1,214 +1,214 @@ -#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; - hook_last = hook; -} - -/// 8KHz interrupt -void Line::poll () { - - switch (mode) { - case ModeRing: - ring(); - break; - - case ModeDT: - tone(DialTone); - break; - - case ModeRBT: - tone(RingBackTone); - break; - - case ModeDisconnect: - tone(BusyTone); - break; - - } - - if (hook) { - // off hook - if (hooktimer) hooktimer --; - - if (! hook_last) { - // dial trigger - dialtimer = DIAL_TIME; - dialcount ++; - } - } else { - // on hook - hooktimer = HOOK_TIME; - } - hook_last = hook; - - if (dialtimer) { - dialtimer --; - - if (dialtimer == 0 && dialcount && ! hook) { - // dial detected - dial.put(dialcount); - dialcount = 0; - } - } else { - dialcount = 0; - } -} - -/// change mode -int Line::enter (enum Mode newmode) { - - // cleanup - switch (mode) { - case ModeRing: - case ModeOff: - power(1); - break; - - case ModeDT: - case ModeRBT: - case ModeBT: - dac = 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; -} - -/// 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; -} - -/// controll power -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) || - (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; - } -} +#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; + hook_last = hook; +} + +/// 8KHz interrupt +void Line::poll () { + + 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) { + // dial trigger + dialtimer = DIAL_TIME; + dialcount ++; + } + } else { + // on hook + hooktimer = HOOK_TIME; + } + hook_last = hook; + + if (dialtimer) { + dialtimer --; + + if (dialtimer == 0 && dialcount && ! hook) { + // dial detected + dial.put(dialcount); + dialcount = 0; + } + } else { + dialcount = 0; + } +} + +/// change mode +int Line::enter (enum Mode newmode) { + + // cleanup + switch (mode) { + case ModeRing: + case ModeOff: + power(1); + break; + + case ModeDT: + case ModeRBT: + case ModeBT: + dac = 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; +} + +/// 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; +} + +/// controll power +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) || + (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; + } +}