// timer6k.c #include "timer6k.h" double MinTime; double MaxTime; // save the old vector, set up new vector, zero out counter // set up timer rate int set_up_new_timer(double freq) { unsigned ms,ls; double divideby; if(freq < (1193180.0/65536.0)) return 0; // can't go below this if(freq > 1193180.0) return 0; // or above this divideby = 1193180.0/freq; divideby+=0.5; // causes a round above .5 ms = (unsigned)divideby >> 8; // get upper 8 for ms ls = (unsigned)divideby & 0xff; // mask off lower 8 for ls frequency = 1193180.0/(double)((ms << 8) + ls); MinTime = 1.0/frequency; MaxTime = (pow(2.0, 32.0)/2.0)/frequency; timer_counter = 0L; disable(); // turn off interrupts outp(0x40, ls); // least significant byte of timer count outp(0x40, ms); // most significant byte of timer count old_timer = getvect(0x1c); setvect(0x1c, new_timer); enable(); // turn interrupts back on return 1; } // restore former table entry and rate void restore_old_timer() { disable(); outp(0x40, 0); // least significant byte of timer count outp(0x40, 0); // most significant byte of timer count setvect(0x1c, old_timer); enable(); } // return the frequency to the caller double get_frequency(void) { return frequency; } // return the value of the counter to the caller long get_timer_counter(void) { return timer_counter; } // wait for seconds and/or fractions of a second void wait(double seconds) { long wait_count, current; if(seconds <= 0) return; if(timer_counter < 0L) return; wait_count = (long)((seconds * frequency) + 0.5); // round at .5 current = timer_counter; while((timer_counter - current) < wait_count); } // the timer interrupt handler interrupt new_timer() { int x; disable(); timer_counter++; for(x=0; x<24; x++) { if(OutputControl[x] == NULL) // not set up continue; if(OutputControl[x]->seton <= 0L) // stay on or not set continue; if(OutputControl[x]->oncount > 0L) { OutputControl[x]->oncount--; if(!OutputControl[x]->oncount) { // keep existing bits but remove this one *OutputControl[x]->PortData &= OutputControl[x]->offmask; // put the result in this node's port register outp(OutputControl[x]->PortAddress, *OutputControl[x]->PortData); OutputControl[x]->offcount = OutputControl[x]->setoff; } } // end if(OutputControl[x]->oncount > 0L) // note that this will not decrement as soon as set // above, but will wait until the next interrupt else if(OutputControl[x]->offcount > 0L) { OutputControl[x]->offcount--; if(!OutputControl[x]->offcount) { // keep existing bits and OR this one in *OutputControl[x]->PortData |= OutputControl[x]->onmask; // put the result in this node's port register outp(OutputControl[x]->PortAddress, *OutputControl[x]->PortData); OutputControl[x]->oncount = OutputControl[x]->seton; } } // end else if(OutputControl[x]->offcount > 0L) } // end for(x=0; x<24; x++) enable(); } // test void show(void) { int x; for(x=0; x<24; x++) { if(OutputControl[x] != NULL) { printf("onmask = %#X seton %ld setoff %ld oncount %ld offcount %ld\n" ,OutputControl[x]->onmask ,OutputControl[x]->seton ,OutputControl[x]->setoff ,OutputControl[x]->oncount ,OutputControl[x]->offcount); } } } // set up Pulse Width Modulation for an output // input is the array number and the port select, // along with the on time and off time in seconds // on time and off time can be fractional seconds int pwm(int arraynumber, int portselect, double ontime, double offtime) { int x; if(offtime < 0) return 0; if(!ConfigureOutput(arraynumber, portselect)) return 0; if(ontime < 0) OutputControl[arraynumber]->seton = -1L; else OutputControl[arraynumber]->seton = (long)((frequency * ontime) + 0.5); if(ontime > 0) { OutputControl[arraynumber]->oncount = OutputControl[arraynumber]->seton; OutputControl[arraynumber]->setoff = (long)((frequency * offtime) + 0.5); // keep existing bits and OR this one in *OutputControl[arraynumber]->PortData |= OutputControl[x]->onmask; // put the result in this node's port register outp(OutputControl[arraynumber]->PortAddress, *OutputControl[x]->PortData); } else { OutputControl[arraynumber]->setoff = 0L; OutputControl[arraynumber]->oncount = 0L; } OutputControl[arraynumber]->offcount = 0L; } // end timer6k.c