Encapsulating ISRs in C++ by Daniel G. Rusch Listing 1 An ISR that canıt access private data. #include class Registration { public: static void interrupt isr(...); private: int valueMyIsrNeeds; }; void interrupt Registration::isr(...) { int port = 0; // error: Member valueMyIsrNeeds // cannot be used without an object valueMyIsrNeeds = inport(port); } void main(void) { Registration regAxis; // code return; } Listing 2 Modification of Chuckıs idea. #include #include class Registration { public: Registration(); static void interrupt isr(...); private: int valueMyIsrNeeds; static Registration* interruptPtr; }; Registration::Registration() { interruptPtr=this; //key to this method } void interrupt Registration::isr(...) { int port = 0; interruptPtr->valueMyIsrNeeds = inport(port); // now this will work } // Static data member must be defined Registration* Registration::interruptPtr = NULL; void main(void) { Registration regAxis; // code return; } Listing 3 Example that uses the contructor to automate pointer maintenance. // Compile as a standard DOS program and it should run fine #include #include #include class TimerClass { public: TimerClass(); unsigned long getTime(); int getValue(); static void interrupt isr(...); private: int variableMyIsrNeeds; static unsigned long time; static TimerClass* interruptPtr; }; TimerClass::TimerClass() { interruptPtr = this; variableMyIsrNeeds = 0; } void interrupt TimerClass::isr(...) { interruptPtr->variableMyIsrNeeds += 2; time++; } unsigned long TimerClass::getTime() { return time; } int TimerClass::getValue() { return variableMyIsrNeeds; } void _interrupt _far (*oldIsr)(...); // Static data member must be defined TimerClass* TimerClass::interruptPtr = NULL; unsigned long TimerClass::time = 0L; void main(void) { clrscr(); oldIsr = _dos_getvect(0x1C); // notice in the next line we can reference isr even though we // have not instantiated any objects of type TimerClass! _dos_setvect(0x1C, TimerClass::isr); TimerClass timerObject1; for(int i = 0; i < 5; i++) { cout << ³\ntimerObject1 time reads: ³ << timerObject1.getTime(); cout << ³\ntimerObject1 value reads: ³ << timerObject1.getValue(); delay(1000); }//End Of for // The section below demonstrates the static function is shared // by all objects of the class....! TimerClass timerObject2; cout << endl << endl << ³Notice that the time value does not get reset, it is static² << endl << ³but the variableMyIsrNeeds does get reset because it² << endl << ³is not shared by both objects!² << endl; for(i = 0; i < 5; i++) { cout << ³\ntimerObject2 time reads: ³ << timerObject2.getTime(); cout << ³\ntimerObject2 value reads: ³ << timerObject2.getValue(); delay(1000); }//End Of for _dos_setvect(0x1C, oldIsr); return; } Listing 4 Pointer changed from a single static variable to an array of static variables. // Compile as a standard DOS program and it should run fine #include #include #include #define MAX 5 class TimerClass { public: TimerClass(); unsigned long getTime(); int getValue(); static void interrupt isr(...); private: int variableMyIsrNeeds; static unsigned long time; static TimerClass* interruptPtr[MAX]; static int index; }; TimerClass::TimerClass() { interruptPtr[index] = this; index++; variableMyIsrNeeds = 0; } void interrupt TimerClass::isr(...) { // Here the ISR can access any object of type MyTimerClass or, as in this example, all // objects of type MyClass. More importantly, the ISR can access the private data as // well as the public data members. for(int i = 0; i < index; i++) interruptPtr[i]->variableMyIsrNeeds += (2 * (i + 1)); time++; } unsigned long TimerClass::getTime() { return time; } int TimerClass::getValue() { return variableMyIsrNeeds; } void _interrupt _far (*oldIsr)(...); // Static data member must be defined TimerClass* TimerClass::interruptPtr[MAX] = {NULL}; int TimerClass::index = 0; unsigned long TimerClass::time = 0L; void main(void) { clrscr(); oldIsr = _dos_getvect(0x1C); // notice in the next line we can reference the isr even though we // have not instantiated any objects of type TimerClass! _dos_setvect(0x1C, TimerClass::isr); TimerClass timerObject1; for(int i = 0; i < 5; i++) { cout << ³\ntimerObject1 time reads: ³ << timerObject1.getTime(); cout << ³\ntimerObject1 value reads: ³ << timerObject1.getValue(); delay(1000); }//End Of for // The section below demonstrates the static function is shared // by all objects of the class....! TimerClass timerObject2; cout << endl << endl << ³Notice that once again the time value does not² << endl << ³get reset, it is static and now we can access both² << endl << ³objectıs variable MyIsrNeeds in the ISR² << endl; for(i = 0; i < 5; i++) { cout << ³\ntimerObject2 time reads: ³ << timerObject2.getTime(); cout << ³\ntimerObject1 value reads: ³ << timerObject1.getValue(); cout << ³\ntimerObject2 value reads: ³ << timerObject2.getValue(); delay(1000); }//End Of for _dos_setvect(0x1C, oldIsr); return; }