mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
Line.cpp@0:f18953137cb4, 2010-12-20 (annotated)
- Committer:
- okini3939
- Date:
- Mon Dec 20 22:55:29 2010 +0000
- Revision:
- 0:f18953137cb4
- Child:
- 1:0f82c574096f
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 0:f18953137cb4 | 1 | #include "Line.h" |
okini3939 | 0:f18953137cb4 | 2 | |
okini3939 | 0:f18953137cb4 | 3 | #define RING_ON FREQ |
okini3939 | 0:f18953137cb4 | 4 | #define RING_OFF (FREQ * 3) |
okini3939 | 0:f18953137cb4 | 5 | #define RING_PULSE (FREQ / 16) |
okini3939 | 0:f18953137cb4 | 6 | #define TONE_DT (FREQ / 400) |
okini3939 | 0:f18953137cb4 | 7 | #define TONE_RBT_ON FREQ |
okini3939 | 0:f18953137cb4 | 8 | #define TONE_RBT_OFF (FREQ * 3) |
okini3939 | 0:f18953137cb4 | 9 | #define TONE_BT_ON (FREQ / 2) |
okini3939 | 0:f18953137cb4 | 10 | #define TONE_BT_OFF FREQ |
okini3939 | 0:f18953137cb4 | 11 | #define HOOK_TIME FREQ |
okini3939 | 0:f18953137cb4 | 12 | #define DIAL_TIME (FREQ / 2) |
okini3939 | 0:f18953137cb4 | 13 | |
okini3939 | 0:f18953137cb4 | 14 | const unsigned short tonetable[TONE_DT] = { |
okini3939 | 0:f18953137cb4 | 15 | 0x7fff, 0x98f4, 0xaf78, 0xc156, 0xcccf, 0xd0c3, 0xcccf, 0xc156, 0xaf78, 0x98f4, |
okini3939 | 0:f18953137cb4 | 16 | 0x7fff, 0x6709, 0x5085, 0x3ea7, 0x332e, 0x2f3a, 0x332e, 0x3ea7, 0x5085, 0x6709 |
okini3939 | 0:f18953137cb4 | 17 | }; |
okini3939 | 0:f18953137cb4 | 18 | |
okini3939 | 0:f18953137cb4 | 19 | 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) { |
okini3939 | 0:f18953137cb4 | 20 | hook.mode(PullUp); |
okini3939 | 0:f18953137cb4 | 21 | mode = ModeOff; |
okini3939 | 0:f18953137cb4 | 22 | status = StatusOk; |
okini3939 | 0:f18953137cb4 | 23 | dialtimer = 0; |
okini3939 | 0:f18953137cb4 | 24 | dialcount = 0; |
okini3939 | 0:f18953137cb4 | 25 | hooktimer = 0; |
okini3939 | 0:f18953137cb4 | 26 | tonecount = 0; |
okini3939 | 0:f18953137cb4 | 27 | hook_last = hook; |
okini3939 | 0:f18953137cb4 | 28 | } |
okini3939 | 0:f18953137cb4 | 29 | |
okini3939 | 0:f18953137cb4 | 30 | /// 8KHz interrupt |
okini3939 | 0:f18953137cb4 | 31 | void Line::poll () { |
okini3939 | 0:f18953137cb4 | 32 | |
okini3939 | 0:f18953137cb4 | 33 | switch (mode) { |
okini3939 | 0:f18953137cb4 | 34 | case ModeRing: |
okini3939 | 0:f18953137cb4 | 35 | ring(); |
okini3939 | 0:f18953137cb4 | 36 | break; |
okini3939 | 0:f18953137cb4 | 37 | |
okini3939 | 0:f18953137cb4 | 38 | case ModeDT: |
okini3939 | 0:f18953137cb4 | 39 | tone(DialTone); |
okini3939 | 0:f18953137cb4 | 40 | break; |
okini3939 | 0:f18953137cb4 | 41 | |
okini3939 | 0:f18953137cb4 | 42 | case ModeRBT: |
okini3939 | 0:f18953137cb4 | 43 | tone(RingBackTone); |
okini3939 | 0:f18953137cb4 | 44 | break; |
okini3939 | 0:f18953137cb4 | 45 | |
okini3939 | 0:f18953137cb4 | 46 | case ModeDisconnect: |
okini3939 | 0:f18953137cb4 | 47 | tone(BusyTone); |
okini3939 | 0:f18953137cb4 | 48 | break; |
okini3939 | 0:f18953137cb4 | 49 | |
okini3939 | 0:f18953137cb4 | 50 | } |
okini3939 | 0:f18953137cb4 | 51 | |
okini3939 | 0:f18953137cb4 | 52 | if (hook) { |
okini3939 | 0:f18953137cb4 | 53 | // off hook |
okini3939 | 0:f18953137cb4 | 54 | if (hooktimer) hooktimer --; |
okini3939 | 0:f18953137cb4 | 55 | |
okini3939 | 0:f18953137cb4 | 56 | if (! hook_last) { |
okini3939 | 0:f18953137cb4 | 57 | // dial trigger |
okini3939 | 0:f18953137cb4 | 58 | dialtimer = DIAL_TIME; |
okini3939 | 0:f18953137cb4 | 59 | dialcount ++; |
okini3939 | 0:f18953137cb4 | 60 | } |
okini3939 | 0:f18953137cb4 | 61 | } else { |
okini3939 | 0:f18953137cb4 | 62 | // on hook |
okini3939 | 0:f18953137cb4 | 63 | hooktimer = HOOK_TIME; |
okini3939 | 0:f18953137cb4 | 64 | } |
okini3939 | 0:f18953137cb4 | 65 | hook_last = hook; |
okini3939 | 0:f18953137cb4 | 66 | |
okini3939 | 0:f18953137cb4 | 67 | if (dialtimer) { |
okini3939 | 0:f18953137cb4 | 68 | dialtimer --; |
okini3939 | 0:f18953137cb4 | 69 | |
okini3939 | 0:f18953137cb4 | 70 | if (dialtimer == 0 && dialcount && ! hook) { |
okini3939 | 0:f18953137cb4 | 71 | // dial detected |
okini3939 | 0:f18953137cb4 | 72 | dial.put(dialcount); |
okini3939 | 0:f18953137cb4 | 73 | dialcount = 0; |
okini3939 | 0:f18953137cb4 | 74 | } |
okini3939 | 0:f18953137cb4 | 75 | } else { |
okini3939 | 0:f18953137cb4 | 76 | dialcount = 0; |
okini3939 | 0:f18953137cb4 | 77 | } |
okini3939 | 0:f18953137cb4 | 78 | } |
okini3939 | 0:f18953137cb4 | 79 | |
okini3939 | 0:f18953137cb4 | 80 | /// change mode |
okini3939 | 0:f18953137cb4 | 81 | int Line::enter (enum Mode newmode) { |
okini3939 | 0:f18953137cb4 | 82 | |
okini3939 | 0:f18953137cb4 | 83 | // cleanup |
okini3939 | 0:f18953137cb4 | 84 | switch (mode) { |
okini3939 | 0:f18953137cb4 | 85 | case ModeRing: |
okini3939 | 0:f18953137cb4 | 86 | case ModeOff: |
okini3939 | 0:f18953137cb4 | 87 | power(1); |
okini3939 | 0:f18953137cb4 | 88 | break; |
okini3939 | 0:f18953137cb4 | 89 | |
okini3939 | 0:f18953137cb4 | 90 | case ModeDT: |
okini3939 | 0:f18953137cb4 | 91 | case ModeRBT: |
okini3939 | 0:f18953137cb4 | 92 | case ModeBT: |
okini3939 | 0:f18953137cb4 | 93 | dac = 0x7fff; |
okini3939 | 0:f18953137cb4 | 94 | break; |
okini3939 | 0:f18953137cb4 | 95 | |
okini3939 | 0:f18953137cb4 | 96 | } |
okini3939 | 0:f18953137cb4 | 97 | |
okini3939 | 0:f18953137cb4 | 98 | mode = newmode; |
okini3939 | 0:f18953137cb4 | 99 | |
okini3939 | 0:f18953137cb4 | 100 | switch (mode) { |
okini3939 | 0:f18953137cb4 | 101 | case ModeReady: |
okini3939 | 0:f18953137cb4 | 102 | // ready |
okini3939 | 0:f18953137cb4 | 103 | power(1); |
okini3939 | 0:f18953137cb4 | 104 | status = StatusOk; |
okini3939 | 0:f18953137cb4 | 105 | break; |
okini3939 | 0:f18953137cb4 | 106 | |
okini3939 | 0:f18953137cb4 | 107 | case ModeDT: |
okini3939 | 0:f18953137cb4 | 108 | case ModeRBT: |
okini3939 | 0:f18953137cb4 | 109 | case ModeBT: |
okini3939 | 0:f18953137cb4 | 110 | // tone |
okini3939 | 0:f18953137cb4 | 111 | tonecount = 0; |
okini3939 | 0:f18953137cb4 | 112 | status = StatusOk; |
okini3939 | 0:f18953137cb4 | 113 | break; |
okini3939 | 0:f18953137cb4 | 114 | |
okini3939 | 0:f18953137cb4 | 115 | case ModeOff: |
okini3939 | 0:f18953137cb4 | 116 | // suspend |
okini3939 | 0:f18953137cb4 | 117 | power(0); |
okini3939 | 0:f18953137cb4 | 118 | status = StatusOk; |
okini3939 | 0:f18953137cb4 | 119 | break; |
okini3939 | 0:f18953137cb4 | 120 | |
okini3939 | 0:f18953137cb4 | 121 | default: |
okini3939 | 0:f18953137cb4 | 122 | status = StatusOk; |
okini3939 | 0:f18953137cb4 | 123 | break; |
okini3939 | 0:f18953137cb4 | 124 | |
okini3939 | 0:f18953137cb4 | 125 | } |
okini3939 | 0:f18953137cb4 | 126 | |
okini3939 | 0:f18953137cb4 | 127 | return 0; |
okini3939 | 0:f18953137cb4 | 128 | } |
okini3939 | 0:f18953137cb4 | 129 | |
okini3939 | 0:f18953137cb4 | 130 | /// return status |
okini3939 | 0:f18953137cb4 | 131 | int Line::scan (enum Scan type) { |
okini3939 | 0:f18953137cb4 | 132 | |
okini3939 | 0:f18953137cb4 | 133 | switch (type) { |
okini3939 | 0:f18953137cb4 | 134 | case ScanMode: |
okini3939 | 0:f18953137cb4 | 135 | return (int)mode; |
okini3939 | 0:f18953137cb4 | 136 | |
okini3939 | 0:f18953137cb4 | 137 | case ScanStatus: |
okini3939 | 0:f18953137cb4 | 138 | return (int)status; |
okini3939 | 0:f18953137cb4 | 139 | |
okini3939 | 0:f18953137cb4 | 140 | case ScanHook: |
okini3939 | 0:f18953137cb4 | 141 | return hooktimer ? HookOn : HookOff; |
okini3939 | 0:f18953137cb4 | 142 | |
okini3939 | 0:f18953137cb4 | 143 | case ScanDial: |
okini3939 | 0:f18953137cb4 | 144 | char c; |
okini3939 | 0:f18953137cb4 | 145 | if (! dial.get(c)) { |
okini3939 | 0:f18953137cb4 | 146 | return c; |
okini3939 | 0:f18953137cb4 | 147 | } |
okini3939 | 0:f18953137cb4 | 148 | break; |
okini3939 | 0:f18953137cb4 | 149 | |
okini3939 | 0:f18953137cb4 | 150 | } |
okini3939 | 0:f18953137cb4 | 151 | |
okini3939 | 0:f18953137cb4 | 152 | return -1; |
okini3939 | 0:f18953137cb4 | 153 | } |
okini3939 | 0:f18953137cb4 | 154 | |
okini3939 | 0:f18953137cb4 | 155 | /// controll power |
okini3939 | 0:f18953137cb4 | 156 | void Line::power (int flg) { |
okini3939 | 0:f18953137cb4 | 157 | if (flg > 0) { |
okini3939 | 0:f18953137cb4 | 158 | xline = 0; |
okini3939 | 0:f18953137cb4 | 159 | wait_ms(1); |
okini3939 | 0:f18953137cb4 | 160 | line = 1; |
okini3939 | 0:f18953137cb4 | 161 | } else |
okini3939 | 0:f18953137cb4 | 162 | if (flg < 0) { |
okini3939 | 0:f18953137cb4 | 163 | line = 0; |
okini3939 | 0:f18953137cb4 | 164 | wait_ms(1); |
okini3939 | 0:f18953137cb4 | 165 | xline = 1; |
okini3939 | 0:f18953137cb4 | 166 | } else { |
okini3939 | 0:f18953137cb4 | 167 | line = 0; |
okini3939 | 0:f18953137cb4 | 168 | xline = 0; |
okini3939 | 0:f18953137cb4 | 169 | } |
okini3939 | 0:f18953137cb4 | 170 | } |
okini3939 | 0:f18953137cb4 | 171 | |
okini3939 | 0:f18953137cb4 | 172 | /// ring |
okini3939 | 0:f18953137cb4 | 173 | void Line::ring () { |
okini3939 | 0:f18953137cb4 | 174 | if (hook && tonecount < RING_ON) { |
okini3939 | 0:f18953137cb4 | 175 | // off hook |
okini3939 | 0:f18953137cb4 | 176 | switch (tonecount % RING_PULSE) { |
okini3939 | 0:f18953137cb4 | 177 | case 0: |
okini3939 | 0:f18953137cb4 | 178 | Line::power(0); |
okini3939 | 0:f18953137cb4 | 179 | break; |
okini3939 | 0:f18953137cb4 | 180 | case RING_PULSE / 10: |
okini3939 | 0:f18953137cb4 | 181 | Line::power(-1); |
okini3939 | 0:f18953137cb4 | 182 | break; |
okini3939 | 0:f18953137cb4 | 183 | case RING_PULSE / 2: |
okini3939 | 0:f18953137cb4 | 184 | Line::power(0); |
okini3939 | 0:f18953137cb4 | 185 | break; |
okini3939 | 0:f18953137cb4 | 186 | case RING_PULSE / 2 + RING_PULSE / 10: |
okini3939 | 0:f18953137cb4 | 187 | Line::power(1); |
okini3939 | 0:f18953137cb4 | 188 | break; |
okini3939 | 0:f18953137cb4 | 189 | } |
okini3939 | 0:f18953137cb4 | 190 | } |
okini3939 | 0:f18953137cb4 | 191 | |
okini3939 | 0:f18953137cb4 | 192 | tonecount ++; |
okini3939 | 0:f18953137cb4 | 193 | if (tonecount >= RING_OFF) tonecount = 0; |
okini3939 | 0:f18953137cb4 | 194 | } |
okini3939 | 0:f18953137cb4 | 195 | |
okini3939 | 0:f18953137cb4 | 196 | /// tone |
okini3939 | 0:f18953137cb4 | 197 | void Line::tone (enum Tone type) { |
okini3939 | 0:f18953137cb4 | 198 | if (! hook && ( type == DialTone || |
okini3939 | 0:f18953137cb4 | 199 | (type == RingBackTone && tonecount < TONE_RBT_ON) || |
okini3939 | 0:f18953137cb4 | 200 | (type == BusyTone && tonecount < TONE_BT_ON) ) ) { |
okini3939 | 0:f18953137cb4 | 201 | // on hook |
okini3939 | 0:f18953137cb4 | 202 | dac.write_u16(tonetable[tonecount % TONE_DT]); |
okini3939 | 0:f18953137cb4 | 203 | } else { |
okini3939 | 0:f18953137cb4 | 204 | // off hook |
okini3939 | 0:f18953137cb4 | 205 | dac.write_u16(0x7fff); |
okini3939 | 0:f18953137cb4 | 206 | } |
okini3939 | 0:f18953137cb4 | 207 | |
okini3939 | 0:f18953137cb4 | 208 | tonecount ++; |
okini3939 | 0:f18953137cb4 | 209 | if ( (type == DialTone && tonecount >= TONE_DT) || |
okini3939 | 0:f18953137cb4 | 210 | (type == RingBackTone && tonecount >= TONE_RBT_OFF) || |
okini3939 | 0:f18953137cb4 | 211 | (type == BusyTone && tonecount >= TONE_BT_OFF) ) { |
okini3939 | 0:f18953137cb4 | 212 | tonecount = 0; |
okini3939 | 0:f18953137cb4 | 213 | } |
okini3939 | 0:f18953137cb4 | 214 | } |