// digi7a.c // The following are known only to the functions in this file. // They can't be modified or even accessed by anything outside this // file except through funtions in this file designed to provide access. // The following are known only to the functions in this file. // They can't be modified or even accessed by anything outside this // file except through funtions in this file designed to provide access. #include "digi7a.h" // ================================================================ // is_closure // 1. Return -1 error indicator if the input // is less than 1 or greater than 88. // // 2. Return 1 if closure is on, 0 if it is off. int is_closure(int input) { int sw_in_port_val,shiftval; // switch in port and shift values if(input < 1 || input > 88) // if the input is less than 1 or greater return -1; // than 88, then return -1 showing an error // we fell through the above so see if the input is less than 25 if(input < 25) { input--; // same as input = input - 1; shiftval = input/3; // divide and neglect the remainder // A 1 is shifted to the proper location. // The result of the shift is XORed with // 0xff and stored in the Port A value, // turning off the desired bit and leaving // all of the others on. // Use porta_val = 1 << shiftval // if the 74LS05 is used, because // the desired operation is to turn // on the bit. porta_val = 0xff ^ (1 << shiftval); // or porta_val = 1 << shiftval with 74LS05 // clear the appropriate Port A bit outp(ppi_porta, porta_val); shiftval = input % 3; // divide and use only the remainder shiftval+=4; // same as shiftval = shiftval + 4; sw_in_port_val = inp(switch_port); // get a number out of the '244 buffer sw_in_port_val>>=shiftval; // shift it to the right shiftval // places to put in bit 0 position sw_in_port_val&=1; // same as sw_in_port_val = sw_in_port_val & 1; sw_in_port_val^=1; // same as sw_in_port_val = sw_in_port_val ^ 1; return sw_in_port_val; } // it's >= 25 if it gets this far input-=25; // same as input = input - 25; shiftval = input/8; // divide and neglect the remainder // A 1 is shifted to the proper location. // The result of the shift is XORed with // 0xff and stored in the Port A value, // turning off the desired bit and leaving // all of the others on. // Use porta_val = 1 << shiftval // if the 74LS05 is used, because // the desired operation is to turn // on the bit. porta_val = 0xff ^ (1 << shiftval); // or porta_val = 1 << shiftval with 74LS05 // clear the appropriate Port A bit outp(ppi_porta, porta_val); shiftval = input % 8; // divide but use only the remainder portb_val = inp(ppi_portb); // get a number from Port B portb_val>>=shiftval; // shift it to the right shiftval // places to put in bit 0 position portb_val&=1; // same as portb_val = portb_val & 1; portb_val^=1; // same as portb_val = portb_val ^ 1; return portb_val; }// end is_closure() // configure the array number location with the port numbers indicated // and to the bit numbers dictated by the port numbers // type: // 0 = uni-directional, no brake // 1 = uni-directional 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) // uni-directional 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 } // free the output control structures void FreeOutputControl(void) { int x; for(x=0; x<24; x++) { if(OutputControl[x] != NULL) free(OutputControl[x]); } } // get the port -- this will grow into an auto-detect function in the future void get_port(void) { base = 0x240; // sw1 = 0 sw2 = 1 sw3 = 1 switch_port = base + 0x18; ppi_porta = base + 0x20; ppi_portb = base + 0x21; ppi_portc = base + 0x22; } // end get_port() void blinker(long on, long off) { int x; long y,z; for(x=0x80; x>0; x>>=1) { outp(ppi_porta, x); printf("%4X",x); for(y=0L; yForwardPortData |= 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 } // 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; } // set up the ppi according to the dictates of the mode argument 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; mode>>=6; // shift the mode value to the right 6 places command = (mode & 0x0c) << 1; // shift bits 2 and 3 into positions 4 and 5 command += (mode & 3); // add in bits 0 and 2 command |= 0x80; // OR in bit 7 for PPI set up outp(control, command); // set according to mode command } // end set_up_ppi() void portboff(void) { outp(ppi_portb, 0); } void motor2(long on, long off) { int x; long y,z; outp(ppi_porta, 0xff); for(y=0L; y