// digi9a.c #include "digi9a.h" // configure the array number location with the port numbers indicated // and to the bit numbers dictated by the port numbers // type: // 0 = unidirctional, no brake // 1 = unidirectional with brake // 2 = pwm line, directional line, no brake // 3 = pwm line, directional line, with brake // 4 = dual pwm lines -- both high = brake // 5 = pwm line and two direction lines as for L298 // 255 = end of points = tells isr not to look anymore & saves time int ConfigureOutput(int arraynumber, int type, int ForwardPortNumber, int ReversePortNumber, int DirectionPortNumber, int BrakePortNumber) { int x; if(arraynumber < 0 || arraynumber > 23) return 0; // illegal number if(ForwardPortNumber < 0 || ForwardPortNumber > 23) return 0; // illegal number if(OutputControl[arraynumber] == NULL) { if((OutputControl[arraynumber] = malloc(sizeof(struct OC))) == NULL) { printf("Not enough memory for output control.\n"); return 0; } } // zero out members memset(OutputControl[arraynumber], 0, sizeof(struct OC)); if(type == 255) { OutputControl[arraynumber]-type = 255; return 1; } // set up the forward masks if(!SetPort(arraynumber, ForwardPortNumber, &OutputControl[arraynumber]->ForwardPortAddress, &OutputControl[arraynumber]->ForwardPortData, &OutputControl[arraynumber]->ForwardOnMask, &OutputControl[arraynumber]->ForwardOffMask)) return 0; if(!type) // unidirectional no brake has forward pwm only return 1; if(type == 1 || type == 3 || type == 5) // 1,3,5 use brake line // (5 uses it for logic lines) { if(!SetPort(arraynumber, BrakePortNumber, &OutputControl[arraynumber]->BrakePortAddress, &OutputControl[arraynumber]->BrakePortData, &OutputControl[arraynumber]->BrakeOnMask, &OutputControl[arraynumber]->BrakeOffMask)) return 0; } if(type == 1 || type == 3 || type == 5) // 1,3,5 use direction line // (5 uses it for logic lines) { if(!SetPort(arraynumber, DirectionPortNumber, &OutputControl[arraynumber]->DirectionPortAddress, &OutputControl[arraynumber]->DirectionPortData, &OutputControl[arraynumber]->DirectionOnMask, &OutputControl[arraynumber]->DirectionOffMask)) return 0; OutputControl[arraynumber]->ReversePortAddress = // reverse is same as forward OutputControl[arraynumber]->ForwardPortAddress; // with a direction line OutputControl[arraynumber]->ReversePortData = OutputControl[arraynumber]->ForwardPortData; OutputControl[arraynumber]->ReverseOnMask = OutputControl[arraynumber]->ForwardOnMask; OutputControl[arraynumber]->ReverseOffMask = OutputControl[arraynumber]->ForwardOffMask; } if(type == 4) // 4 is a dual pwm so has a separate reverse line { if(!SetPort(arraynumber, ReversePortNumber, &OutputControl[arraynumber]->ReversePortAddress, &OutputControl[arraynumber]->ReversePortData, &OutputControl[arraynumber]->ReverseOnMask, &OutputControl[arraynumber]->ReverseOffMask)) return 0; } return 1; } // portflag settings: // A CU B CL // x x x x // low = output, hi = input // example: // 0101 // A = out, CU = in, B = out, CL = in int portflag = 0x0f; // set by set_up_ppi() -- init to all inputs // set up flags, etc. for an output port int SetPort(int arraynumber, int PortNumber, int *PortAddress, int **PortData, int *OnMask, int *OffMask) { int x; if(arraynumber < 0 || arraynumber > 23) return 0; if(PortNumber < 0 || PortNumber > 23) return ClearPort(arraynumber); // error - free port & return 0 *OnMask = 1 << (PortNumber & 7); // shift by bits[2:0] *OffMask = ~*OnMask; x = PortNumber >> 3; // the port number is in bits 3 and 4 switch(x) // 0 = Port A, 1 = Port B, 2 = Port C { case 0: if(portflag & 8) // bit 3 hi = A in, not out return ClearPort(arraynumber); *PortAddress = ppi_porta; // address for Port A *PortData = &porta_val; // point to Port A data value break; case 1: if(portflag & 2) // bit 1 hi = B in, not out return ClearPort(arraynumber); *PortAddress = ppi_portb; // address for Port B *PortData = &portb_val; // point to Port B data value break; case 2: if(portflag & 1 && *OnMask &0x0f) // bit 0 hi = CL in, not out return ClearPort(arraynumber); if(portflag & 4 && *OnMask &0xf0) // bit 2 hi = CU in, not out return ClearPort(arraynumber); *PortAddress = ppi_portc; // address for Port C *PortData = &portc_val; // point to Port C data value break; } return 1; } // set the last array location so isr won't waste time looking int SetLast(int arraynumber) { if(arraynumber < 0 || arraynumber > 23) return 0; if(OutputControl[arraynumber] == NULL) { if((OutputControl[arraynumber] = malloc(sizeof(struct OC))) == NULL) { printf("Not enough memory for output control.\n"); return 0; } } // zero out members memset(OutputControl[arraynumber], 0, sizeof(struct OC)); OutputControl[arraynumber]->type = 255; // show as last } // free and null out error location int ClearPort(int arraynumber) { if(OutputControl[arraynumber] != NULL) { free(OutputControl[arraynumber]); OutputControl[arraynumber] = NULL; } return 0; // always 0 -- illegal number } // ================================================================ // set_up_ppi() // set up the ppi according to the dictates of the mode argument // The new modes are as follows, along with the value after shifting: // bits 3210 // Aout_CUout_Bout_CLout = 0x000 >> 6 = 0000 // Aout_CUout_Bout_CLin = 0x040 >> 6 = 0001 // Aout_CUout_Bin_CLout = 0x080 >> 6 = 0010 // Aout_CUout_Bin_CLin = 0x0C0 >> 6 = 0011 // Aout_CUin_Bout_CLout = 0x100 >> 6 = 0100 // Aout_CUin_Bout_CLin = 0x140 >> 6 = 0101 // Aout_CUin_Bin_CLout = 0x180 >> 6 = 0110 // Aout_CUin_Bin_CLin = 0x1C0 >> 6 = 0111 // Ain_CUout_Bout_CLout = 0x200 >> 6 = 1000 // Ain_CUout_Bout_CLin = 0x240 >> 6 = 1001 // Ain_CUout_Bin_CLout = 0x280 >> 6 = 1010 // Ain_CUout_Bin_CLin = 0x2C0 >> 6 = 1011 // Ain_CUin_Bout_CLout = 0x300 >> 6 = 1100 // Ain_CUin_Bout_CLin = 0x340 >> 6 = 1101 // Ain_CUin_Bin_CLout = 0x380 >> 6 = 1110 // Ain_CUin_Bin_CLin = 0x3C0 >> 6 = 1111 // // PPI setup bits: 4 3 2 1 0 // A CU B CL // // CU = C Upper and CL = C Lower // A 0 at a bit location makes the port an output, // and a 1 makes it an input // Consider Aout_CUin_Bout_CLin = 0101 after right shift // 1. put bits 2 and 3 into positions 3 and 4: 00001000 // 2. add in bits 0 and 1: 00001001 // 3. OR in 0x80 which says program ports: 10001001 // bit 4 = 0, so A is an output // bit 3 = 1, so CU is an input // bit 1 = 0, so B is an output // bit 0 = 1, so CL is an input // ================================================================ void set_up_ppi(int mode) { unsigned control = base + 0x23; int command; // make certain control locations start at NULL for(command=0; command<24; command++) OutputControl[command] = NULL; if(mode >= 15) mode >>= 6; // new mode numbers get shifted first portflag = mode; // see above -- used to check port setup command = (mode & 0x0c) << 1; // shift bits 2 and 3 into positions 3 and 4 command += (mode & 3); // add in bits 0 and 1 command |= 0x80; // OR in bit 7 for PPI set up outp(control, command); // set according to mode command } // end set_up_ppi() // ================================================================ // is_closure // 1. Return -1 error indicator if the input // is less than 1 or greater than 67. // // 2. If there is a fall-through from the above and the input // is less than 4, return the status based on switch_port. // // 3. If there is a fall-through from both of the above, then // return the status based on the matrix: // |-----------------------| // Port A bit 0| 4| 5| 6| 7| 8| 9|10|11| // Port A bit 1|12|13|14|15|16|17|18|19| // Port A bit 2|20|21|22|23|24|25|26|27| // Port A bit 3|28|29|30|31|32|33|34|35| // Port A bit 4|36|37|38|39|40|41|42|43| // Port A bit 5|44|45|46|47|48|49|50|51| // Port A bit 6|52|53|54|55|56|57|58|59| // Port A bit 7|60|61|62|63|64|65|66|67| // |-----------------------| // Port B bits 0 1 2 3 4 5 6 7 // ================================================================ int is_closure(int input) { if(input < 1 || input > 67) // if the input is less than 1 or greater return -1; // than 67, then return -1 showing an error // we fell through the above so see if input is less than 4 if(input < 4) return ((inp(switch_port) >> (input + 3)) & 1) ^ 1; // yes, return using switch_port // input is >= 4 so look at the matrix // by first setting up Port A to take the appropriate row bit low porta_val = (~(1 << ( (input - 4) / 8) )) & 0xff; // clear the appropriate Port A bit outp(ppi_porta, porta_val); // determine what column bit to look at for this input portb_mask = (1 << ((input - 4) % 8)) & 0xff; // a closure will cause a low, so invert the return if(!(inp(ppi_portb) & portb_mask)) return 1; return 0; }// end is_closure() // get the port -- this will grow into an auto-detect function in the future unsigned oldget_port(void) { base = 0x200; // all switches on -- change if desired switch_port = base + 0x18; ppi_porta = base + 0x20; ppi_portb = base + 0x21; ppi_portc = base + 0x22; return base; } // end get_port() // find hardware port if one exists unsigned get_port(void) { int x; static unsigned local_port; unsigned int not_ready_count,ready_count; if(local_port == 32767) return 0; if(local_port > 0) return local_port; for(x=0x200; x<0x3c0; x+=0x40) { not_ready_count = 32767; ready_count = 32767; outp(x,0); /* start conversion */ while((inp(x+0x18) & 0x80) && --not_ready_count); /* wait for not ready */ while(!(inp(x+0x18) & 0x80) && --ready_count); /* wait for ready */ //printf("ready_count = %d\n",ready_count); if(ready_count < 32767 && ready_count > 0) { local_port = base = x; switch_port = base + 0x18; ppi_porta = base + 0x20; ppi_portb = base + 0x21; ppi_portc = base + 0x22; return base; } } local_port = 32767; return 0; } void blinker(long on, long off) { int x; long y,z; for(x=0x80; x>0; x>>=1) { outp(ppi_porta, x); for(y=0L; y0; x>>=1) { porta_val |= x; outp(ppi_porta, porta_val); printf("%3X",porta_val); for(z=0L; zForwardSetOn = -1L; // keep existing bits and OR this one in *OutputControl[arraynumber]->ForwardPortData |= OutputControl[arraynumber]->ForwardOnMask; // put the result in this node's port register outp(OutputControl[arraynumber]->ForwardPortAddress, *OutputControl[arraynumber]->ForwardPortData); return 1; } // turn off an output node int TurnOff(int arraynumber) { if(OutputControl[arraynumber] == NULL) { printf("can't turn off -- location %d not set up\n",arraynumber); return 0; // node not set up } // signal service routine that this is not pwm OutputControl[arraynumber]->ForwardSetOn = -1L; // keep existing bits but remove this one *OutputControl[arraynumber]->ForwardPortData &= OutputControl[arraynumber]->ForwardOffMask; // put the result in this node's port register outp(OutputControl[arraynumber]->ForwardPortAddress, *OutputControl[arraynumber]->ForwardPortData); return 1; } // ======================== old config routine ============================ // configure the array number location to a port // and bit number dictated by portselect int oldConfigureOutput(int arraynumber, int portselect) { int x; if(arraynumber < 0 || arraynumber > 23) { printf("arraynumber error --- %d\n",arraynumber); return 0; // illegal number } if(portselect < 0 || portselect > 23) { printf("portselect error --- %d\n",portselect); return 0; // illegal number } if(OutputControl[arraynumber] == NULL) { if((OutputControl[arraynumber] = malloc(sizeof(struct OC))) == NULL) { printf("Not enough memory\n"); return 0; } } // zero out members memset(OutputControl[arraynumber], 0, sizeof(struct OC)); x = portselect >> 3; // the port number is in bits 3 and 4 switch(x) // 0 = Port A, 1 = Port B, 2 = Port C { case 0: OutputControl[arraynumber]->ForwardPortAddress = ppi_porta; // address for Port A OutputControl[arraynumber]->ForwardPortData = &porta_val; // point to Port A data value break; case 1: OutputControl[arraynumber]->ForwardPortAddress = ppi_portb; // address for Port B OutputControl[arraynumber]->ForwardPortData = &portb_val; // point to Port B data value break; case 2: OutputControl[arraynumber]->ForwardPortAddress = ppi_portc; // address for Port C OutputControl[arraynumber]->ForwardPortData = &portc_val; // point to Port C data value break; } // shift by bits[2:0] OutputControl[arraynumber]->ForwardOnMask = 1 << (portselect & 7); OutputControl[arraynumber]->ForwardOffMask = ~OutputControl[arraynumber]->ForwardOnMask; /* add double slash rem to print debug statements printf("arraynum=%02d port select=%02d ",arraynumber,portselect); printf("Addr=%#X " ,OutputControl[arraynumber]->ForwardPortAddress); printf("*Data=%X " ,*OutputControl[arraynumber]->ForwardPortData); printf("onmsk="); for(x=128; x>0; x/=2) { if(x & OutputControl[arraynumber]->ForwardOnMask) printf("1"); else printf("0"); } printf(" offmsk="); for(x=128; x>0; x/=2) { if(x & OutputControl[arraynumber]->ForwardOffMask) printf("1"); else printf("0"); } printf("\n"); add double slash rem to print debug statements */ return 1; } // end digi9a.c