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