Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
IEC60601-1-8.cpp
00001 /**************************************************************** 00002 * IEC601601-1-8 00003 * 00004 * This modules provides the IEC Medical Alert tones. 00005 * 00006 * 00007 * Copyright(C) 2007, NXP Semiconductor 00008 * All rights reserved. 00009 * 00010 * Port to mbed 2012 (WH) 00011 ****************************************************************/ 00012 #include "mbed.h" 00013 #include "IEC60601-1-8.h" 00014 00015 #define DEBUG_ON 0 // Activate Testpins for timing 00016 #if(DEBUG_ON) 00017 // Activate Testpins for timing 00018 DigitalOut TimInt(p19); 00019 DigitalOut SeqInt(p20); 00020 #endif 00021 00022 #define AMPL 200 // Output Amplitude 00023 #define PI 3.1415926 00024 #define FSAMPLE 25000 // Timer Reload Frequency 00025 00026 00027 // define rise and fall time of tones 00028 #define HP_RISE 12 // rise time setting for high priority tones (12 = ~20ms Tr) 00029 // decrease to make slower, increase to make faster 00030 #define HP_FALL 12 // fall time setting for high priority tones (12 = ~20ms Tf) 00031 // decrease to make slower, increase to make faster 00032 #define MP_RISE 8 // rise time setting for high priority tones (8 = ~30ms Tr) 00033 // decrease to make slower, increase to make faster 00034 #define MP_FALL 8 // fall time setting for high priority tones (8 = ~30ms Tf) 00035 // decrease to make slower, increase to make faster 00036 00037 00038 Note_Type const _TuneSequence [][5] = {{C4,C4,C4,C4,C4}, // general 00039 {C5,B4,A4,G4,F4}, // oxygen 00040 {C4,A4,F4,A4,F4}, // ventilation 00041 {C4,E4,G4,G4,C5}, // cardiovascular 00042 {C4,D4,E4,F4,G4}, // temperature 00043 {C5,D4,G4,C5,D4}, // drug_delivery 00044 {C4,Fsharp4,C4,C4,Fsharp4}, // perfusion 00045 {C5,C4,C4,C5,C4}, // power_fail 00046 // {E4,C4,0,0,0}}; // low_alarm 00047 {E4,C4,C4,C4,C4}}; // low_alarm 00048 00049 float const _FreqArray[][5]= {{261.626,523.252,784.878,1046.50,1308.13}, // C4 00050 {293.67,587.34,881.01,1174.7,1468.3}, // D4 00051 {329.63,659.26,988.89,1318.52,1648.15}, // E4 00052 {349.23,698.46,1047.69,1396.9,1746.15}, // F4 00053 {369.99,739.98,1109.97,1479.96,1849.95}, // FSharp4 00054 {392.00,784.00,1176.0,1568.0,1960.0}, // G4 00055 {440.000,880.00,1320.0,1760.00,2200.00}, // A4 00056 {493.88,987.76,1481.64,1975.5,2469.4}, // B4 00057 {523.251,1046.50,1569.756,2093.00,2616.25}}; // C5 00058 00059 unsigned char _ToneWeights[] = {255,255,255,255,255}; // used for test and 00060 // adjusting harmonic levels 00061 00062 struct wave _Waves[9][5]; // 'Waves' holds tone gen coefficients and variables 00063 // the coefficients are calculated during initialization. 00064 00065 00066 IEC60601::IEC60601() { 00067 00068 _InitDAC(); 00069 _InitSequencer(); 00070 _InitToneCoefArray(); 00071 _ticker.attach_us(this, &IEC60601::_TimerInteruptHandler, 40); 00072 }; 00073 00074 00075 00076 void IEC60601::TurnOnAlarm(Prio_Type priority, Alarm_Type alarm_type) { 00077 00078 _priority = priority; 00079 _alarm_type = alarm_type; 00080 00081 _mscount = 0; 00082 _sequence = 1; 00083 00084 } 00085 00086 void IEC60601::TurnOffAlarm(void) { 00087 _sequence = 0; 00088 } 00089 00090 void IEC60601::TestAlarm(Note_Type active_note, int w0, int w1, int w2, int w3, int w4) { 00091 00092 _priority = TEST; 00093 00094 _active_note = active_note; 00095 _ToneWeights[0]= w0; 00096 _ToneWeights[1]= w1; 00097 _ToneWeights[2]= w2; 00098 _ToneWeights[3]= w3; 00099 _ToneWeights[4]= w4; 00100 00101 _mscount = 0; 00102 _sequence = 1; 00103 } 00104 00105 00106 // This modules provides the note sequencers and envelope control 00107 // functions for the alarm notes for the IEC Medical Alert tone demo. 00108 00109 void IEC60601::_InitSequencer(void) { 00110 _envelope_on = false; 00111 _envelope_off = false; 00112 } 00113 00114 00115 void IEC60601::_TurnOnNote(void) { 00116 _envelope = 0; 00117 _note_on = true; 00118 _envelope_on = true; 00119 } 00120 00121 void IEC60601::_TurnOffNote(void) { 00122 _note_on = false; 00123 } 00124 00125 00126 void IEC60601::_HighPriSequence (void) { 00127 00128 switch (_mscount) { 00129 case 1: 00130 _active_note = _TuneSequence [_alarm_type][0]; // 1rst note of sequence 00131 _note_level = 170; 00132 _TurnOnNote(); 00133 break; 00134 case 145: // 145 ms (trise + tduration) 00135 _note_on = false; // begin decay as note turns "off" 00136 break; 00137 case 224: 00138 _active_note = _TuneSequence [_alarm_type][1]; // 2nd note of sequence 00139 _note_level = 255; 00140 _TurnOnNote(); 00141 break; 00142 case 368: 00143 _note_on = false; // begin decay as note turns "off" 00144 break; 00145 case 447: 00146 _active_note = _TuneSequence [_alarm_type][2]; // 3rd note of sequence 00147 _note_level = 255; 00148 _TurnOnNote(); 00149 break; 00150 case 591: 00151 _note_on = false; // begin decay as note turns "off" 00152 break; 00153 case 835: 00154 _active_note = _TuneSequence [_alarm_type][3]; // 4th note of sequence 00155 _note_level = 255; 00156 _TurnOnNote(); 00157 break; 00158 case 979: 00159 _note_on = false; // begin decay as note turns "off" 00160 break; 00161 case 1058: 00162 _active_note = _TuneSequence [_alarm_type][4]; // 5th note of sequence 00163 _note_level = 255; 00164 _TurnOnNote(); 00165 break; 00166 case 1202: 00167 _note_on = false; // begin decay as note turns "off" 00168 break; 00169 00170 case 1250: // allows for fall time of envelope 00171 if (_sequence == 2) { // Done after one repeat 00172 _sequence = 0; 00173 _mscount = 0; 00174 } 00175 break; 00176 case 1750: 00177 if (_sequence == 1) { // If this is the first time through, repeat 00178 _sequence = 2; 00179 } 00180 _mscount = 0; 00181 break; 00182 } 00183 } 00184 00185 00186 void IEC60601::_MedPriSequence (void) { 00187 00188 switch (_mscount) { 00189 case 1: 00190 _active_note = _TuneSequence [_alarm_type][0]; 00191 _note_level = 170; 00192 _TurnOnNote(); 00193 break; 00194 case 221: // 221 ms (trise(30) + tduration(190)+ start(1)) 00195 _note_on = false; // begin decay as note turns "off" 00196 break; 00197 case 441: 00198 _active_note = _TuneSequence [_alarm_type][1]; // 2nd note of sequence 00199 _note_level = 255; 00200 _TurnOnNote(); 00201 break; 00202 case 661: 00203 _note_on = false; // begin decay as note turns "off" 00204 break; 00205 case 881: 00206 _active_note = _TuneSequence [_alarm_type][2]; // 3rd note of sequence 00207 _note_level = 255; 00208 _TurnOnNote(); 00209 break; 00210 case 1101: 00211 _note_on = false; // begin decay as note turns "off" 00212 break; 00213 case 1151: // allows for fall time of envelope 00214 _sequence = 0; // Medium Prio does not repeat 00215 _mscount = 0; 00216 } 00217 00218 } 00219 00220 void IEC60601::_LowPriSequence (void) { 00221 00222 switch (_mscount) { 00223 case 1: 00224 _active_note = _TuneSequence [_alarm_type][0]; 00225 _note_level = 170; 00226 _TurnOnNote(); 00227 break; 00228 case 261: // 261 ms (trise(35) + tduration(225)) 00229 _note_on = false; // begin decay as note turns "off" 00230 break; 00231 case 521: 00232 _active_note = _TuneSequence [_alarm_type][1]; // 2nd note of sequence 00233 _note_level = 255; 00234 _TurnOnNote(); 00235 break; 00236 case 781: 00237 _note_on = false; // begin decay as note turns "off" 00238 break; 00239 case 816: // Low Prio does not repeat 00240 _sequence = 0; 00241 _mscount = 0; 00242 } 00243 } 00244 00245 void IEC60601::_TestSequence (void) { 00246 00247 switch (_mscount) { 00248 case 1: 00249 // _active_note = _TuneSequence [_alarm_type][0]; 00250 _note_level = 255; 00251 _TurnOnNote(); 00252 break; 00253 00254 case 1000: 00255 _note_on = false; // begin decay as note turns "off" 00256 break; 00257 00258 case 1035: 00259 00260 for (int i=0; i<5; i++) { // Restore weights 00261 _ToneWeights[i] = 255; 00262 }; 00263 _sequence = 0; // Test does not repeat 00264 _mscount = 0; 00265 break; 00266 } 00267 } 00268 00269 void IEC60601::_EnvelopeControl(void) { 00270 00271 if (_note_on) { 00272 if (_envelope >= _note_level) { 00273 _envelope = _note_level; 00274 } 00275 else { 00276 if (_priority == HIGH) { 00277 _envelope += HP_RISE; // high priority risetime control 00278 } 00279 else { 00280 _envelope += MP_RISE; // Medium priority risetime control 00281 } 00282 } 00283 } 00284 else { 00285 if (_envelope > 0) { 00286 if (_priority == HIGH) { 00287 _envelope -= HP_FALL; // high priority falltime control 00288 } 00289 else { 00290 _envelope -= MP_FALL; // Medium priority falltime control 00291 } 00292 } 00293 } 00294 if ((_envelope <= 0) && (!_note_on) && (_envelope_on) ) { 00295 _envelope = 0; 00296 _envelope_off = true; // synchronize with zero cross 00297 } 00298 } 00299 00300 00301 00302 // This module generates multiple sine waves that are combined 00303 // to generate tones that contain a fundamental and 4 harmonics 00304 // per the IEC60601-1-8 Medical Alarm specification 00305 00306 void IEC60601::_InitDAC(void) { 00307 00308 LPC_PINCON->PINSEL1 &= ~0x00300000; // enable DAC P0.26 00309 LPC_PINCON->PINSEL1 |= 0x00200000; 00310 LPC_PINCON->PINMODE1 &= ~0x00300000; // disable Rs on P0.26 00311 LPC_PINCON->PINMODE1 |= 0x00200000; 00312 00313 LPC_DAC->DACR = 0x8000; // init DAC to half on voltage 00314 } 00315 00316 00317 void IEC60601::_InitToneCoefArray(void) { // generate the coefficients and init array for tones 00318 00319 unsigned char n; 00320 unsigned char j; 00321 00322 for (j=0;j<9;j++) // Initialize all nine scale tones (C4-C5) 00323 { 00324 for (n=0;n<5;n++) // fundamental and 4 harmonics for IEC60601-1-8 00325 { 00326 _Waves[j][n].coef = ((cos (2*PI*(float)(_FreqArray[j][n]/FSAMPLE)))* 32768) ; // 2* taken out, put in final calc as a shift 00327 _Waves[j][n].y1 = 0; 00328 _Waves[j][n].y2 = ((sin (2*PI*(float)((_FreqArray[j][n]/FSAMPLE))) * AMPL * 32768)); // Try 8388608 (+8 bits) w/ long coef 00329 } 00330 } 00331 } 00332 00333 00334 void IEC60601::_GenerateMultiTone (struct wave *t) { 00335 long int y; 00336 int i; 00337 int env_weights; 00338 long int output; 00339 static long int output_old; 00340 00341 output = 0; // clear output accumulator 00342 for (i=0; i<5; i++) { // cycle through the 5 structures in the array 00343 y = ((t->coef *(long long)(t->y1)>>14)) - t->y2; // Goertzel Calculation 00344 t->y2 = t->y1; // store for next time 00345 t->y1 = y; // store for next time 00346 env_weights = _envelope * _ToneWeights[i]>>8; 00347 output += ((t->y1 * env_weights) >> 8); // sum fundamental and harmonics 00348 t++; // increment structure pointer 00349 } 00350 00351 //// DAC->DACR = ((output >> 10) & 0xFFC0) + 0x8000; // make unsigned and output to DAC 00352 ///// Adapt to mbed !!!! 00353 LPC_DAC->DACR = ((output >> 10) & 0xFFC0) + 0x8000; // make unsigned and output to DAC 00354 00355 00356 if ((output >= 0) && (output_old <= 0)) { // zero crossing detect 00357 if (_envelope_off && (!_note_on)) { 00358 _envelope_on = false; // sychronizes turn off with zero cross 00359 _envelope_off = false; // reset envelope flag 00360 } 00361 } 00362 output_old = output; 00363 } 00364 00365 #if(0) 00366 void IEC60601::_OutputTones(Note_Type note, unsigned char level) { 00367 00368 _note_level = level; 00369 _GenerateMultiTone (&Waves[note][0]); 00370 } 00371 #endif 00372 00373 00374 void IEC60601::_TimerInteruptHandler (void){ 00375 static int timeval = 0; 00376 00377 #if(DEBUG_ON) 00378 // Activate Testpins for timing 00379 TimInt = 1; 00380 #endif 00381 00382 if (_envelope_on) { 00383 //Oude code 00384 // _OutputTones(_active_note, _note_level); // parameters are set in sequencer 00385 00386 _GenerateMultiTone (&_Waves[_active_note][0]); // parameters set in sequencer 00387 } 00388 00389 timeval++; 00390 if (timeval == 25) { // millisecond interval (@ 25 khz sample rate) 00391 00392 #if(DEBUG_ON) 00393 // Activate Testpins for timing 00394 SeqInt=1; 00395 #endif 00396 if (_sequence != 0) { 00397 switch (_priority) { 00398 case HIGH: 00399 _HighPriSequence(); 00400 break; 00401 case MEDIUM: 00402 _MedPriSequence(); 00403 break; 00404 case LOW: 00405 _LowPriSequence(); 00406 break; 00407 case TEST: 00408 _TestSequence(); 00409 break; 00410 } 00411 } 00412 timeval = 0; // clear interval counter 00413 _mscount++; // increment ms counter 00414 _EnvelopeControl(); 00415 00416 #if(DEBUG_ON) 00417 // Activate Testpins for timing 00418 SeqInt=0; 00419 #endif 00420 } 00421 00422 #if(DEBUG_ON) 00423 // Activate Testpins for timing 00424 TimInt = 0; 00425 #endif 00426 00427 } 00428 00429 00430
Generated on Wed Jul 13 2022 14:29:31 by
1.7.2
IEC60601-1-8 Audible Alert Generator