Wim Huiskamp / Mbed 2 deprecated mbed_audio_alert

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers IEC60601-1-8.cpp Source File

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