📄 hal_ppmc.c
字号:
/* check to see if a port address was specified */ if ( port_addr[busnum] == 0 ) { /* nope, skip to next bus */ continue; } rtapi_print_msg(RTAPI_MSG_INFO, "PPMC: checking EPP bus %d at port %04X\n", busnum, port_addr[busnum]); boards = 0; /* allocate memory for bus data - this is not shared memory */ bus = kmalloc(sizeof(bus_data_t), GFP_KERNEL); if (bus == 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PPMC: ERROR: kmalloc() failed\n"); rv = -1; /* skip to next bus */ continue; } /* clear the bus data structure */ bus->busnum = busnum; bus->have_master = 0; bus->last_digout = 0; bus->last_digin = 0; bus->last_stepgen = 0; bus->last_pwmgen = 0; bus->last_encoder = 0; /* clear the slot data structures (part of the bus struct) */ for ( slotnum = 0 ; slotnum < NUM_SLOTS ; slotnum ++ ) { /* clear slot valid flag in bus struct */ bus->slot_valid[slotnum] = 0; /* point to slot struct */ slot = &(bus->slot_data[slotnum]); /* clear stuff */ slot->id = 0; slot->ver = 0; slot->strobe = 0; slot->slot_base = slotnum * SLOT_SIZE; slot->port_addr = port_addr[busnum]; slot->first_rd = 31; slot->last_rd = 0; slot->first_wr = 31; slot->last_wr = 0; /* clear EPP read and write caches */ for ( n = 0 ; n < 32 ; n++ ) { slot->rd_buf[n] = 0; slot->wr_buf[n] = 0; } /* clear function pointers */ slot->num_rd_functs = 0; slot->num_wr_functs = 0; for ( n = 0 ; n < MAX_FUNCT ; n++ ) { slot->rd_functs[n] = NULL; slot->wr_functs[n] = NULL; } slot->digout = NULL; slot->digin = NULL; slot->stepgen = NULL; slot->pwmgen = NULL; slot->encoder = NULL; } /* scan the bus */ for ( slotnum = 0 ; slotnum < NUM_SLOTS ; slotnum ++ ) { /* point to slot struct */ slot = &(bus->slot_data[slotnum]); /* rv1 is used to flag errors that fail one bus */ rv1 = 0; rtapi_print_msg(RTAPI_MSG_INFO, "PPMC: slot %d: ", slotnum); /* check slot */ idcode = SelRead(slot->slot_base+SLOT_ID_OFFSET, slot->port_addr); if ( ( idcode == 0 ) || ( idcode == 0xFF ) ) { slot->id = 0; slot->ver = 0; rtapi_print_msg(RTAPI_MSG_INFO, "nothing detected\n"); ClrTimeout(slot->port_addr); /* skip to next slot */ continue; } rtapi_print_msg(RTAPI_MSG_INFO, "ID code: %02X ", idcode); slot->id = id = idcode & 0xF0; slot->ver = ver = idcode & 0x0F; /* mark slot as occupied */ bus->slot_valid[slotnum] = 1; /* do board specific init and configuration */ switch ( id ) { case 0x10: boards++; rtapi_print_msg(RTAPI_MSG_INFO, "PPMC encoder card\n"); rv1 += export_encoders(slot, bus); break; case 0x20: boards++; rtapi_print_msg(RTAPI_MSG_INFO, "PPMC DAC card\n"); break; case 0x30: boards++; rtapi_print_msg(RTAPI_MSG_INFO, "PPMC Digital I/O card\n"); break; case 0x40: boards++; rtapi_print_msg(RTAPI_MSG_INFO, "Univ. Stepper Controller\n"); rv1 += export_UxC_digin(slot, bus); rv1 += export_UxC_digout(slot, bus); rv1 += export_USC_stepgen(slot, bus); rv1 += export_encoders(slot, bus); /* the USC occupies two slots, so skip the second one */ slotnum++; break; case 0x50: boards++; rtapi_print_msg(RTAPI_MSG_INFO, "Univ. PWM Controller\n"); rv1 += export_UxC_digin(slot, bus); rv1 += export_UxC_digout(slot, bus); rv1 += export_UPC_pwmgen(slot, bus); rv1 += export_encoders(slot, bus); /* the UPC occupies two slots, so skip the second one */ slotnum++; break; default: rtapi_print_msg(RTAPI_MSG_ERR, "Unknown! (ERROR)\n"); /* mark slot as empty */ bus->slot_valid[slotnum] = 0; /* mark bus failed */ rv1 = -1; break; } } /* end of slot loop */ if ( rv1 != 0 ) { /* error during slot scan, already printed */ rv = -1; /* skip to next bus */ continue; } if ( boards == 0 ) { rtapi_print_msg(RTAPI_MSG_ERR, "PPMC: ERROR: no boards found on bus %d, port %04X\n", busnum, port_addr[busnum] ); rv = -1; /* skip to next bus */ continue; } /* export functions */ rtapi_snprintf(buf, HAL_NAME_LEN, "ppmc.%d.read", busnum); rv1 = hal_export_funct(buf, read_all, &(bus_array[busnum]), 1, 0, comp_id); if (rv1 != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PPMC: ERROR: read funct export failed\n"); rv = -1; /* skip to next bus */ continue; } rtapi_snprintf(buf, HAL_NAME_LEN, "ppmc.%d.write", busnum); rv1 = hal_export_funct(buf, write_all, &(bus_array[busnum]), 1, 0, comp_id); if (rv1 != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PPMC: ERROR: write funct export failed\n"); rv = -1; /* skip to next bus */ continue; } /* save pointer to bus data */ bus_array[busnum] = bus; rtapi_print_msg(RTAPI_MSG_INFO, "PPMC: bus %d complete\n", busnum); } /* restore saved message level */ rtapi_set_msg_level(msg); /* final check for errors */ if ( rv != 0 ) { /* something went wrong, cleanup and exit */ rtapi_print_msg(RTAPI_MSG_ERR, "PPMC: shutting down\n"); for ( busnum = 0 ; busnum < MAX_BUS ; busnum++ ) { /* check to see if memory was allocated for bus */ if ( bus_array[busnum] != NULL ) { /* save ptr to memory block */ bus = bus_array[busnum]; /* mark it invalid so RT code won't access */ bus_array[busnum] = NULL; /* and free the block */ kfree(bus); } } /* disconnect from HAL */ hal_exit(comp_id); return -1; } rtapi_print_msg(RTAPI_MSG_INFO, "PPMC: driver installed\n"); return 0;}void rtapi_app_exit(void){ int busnum, n, m; bus_data_t *bus; rtapi_print_msg(RTAPI_MSG_ERR, "PPMC: shutting down\n"); for ( busnum = 0 ; busnum < MAX_BUS ; busnum++ ) { /* check to see if memory was allocated for bus */ if ( bus_array[busnum] != NULL ) { /* save ptr to memory block */ bus = bus_array[busnum]; /* mark it invalid so RT code won't access */ bus_array[busnum] = NULL; /* want to make sure everything is turned off */ /* write zero to the first byte of each slot */ for ( n = 0 ; n < 256 ; n += 16 ) { SelWrt(0, n, bus->slot_data[0].port_addr); /* and to the remainder of the slot */ for ( m = 1 ; m < 32 ; m++ ) { WrtMore(0, bus->slot_data[0].port_addr); } } /* and free the memory block */ kfree(bus); } } /* disconnect from HAL */ hal_exit(comp_id);}/************************************************************************ REALTIME FUNCTIONS *************************************************************************/static void read_all(void *arg, long period){ bus_data_t *bus; slot_data_t *slot; int slotnum, functnum; unsigned char n, eppaddr; /* get pointer to bus data structure */ bus = *(bus_data_t **)(arg); /* test to make sure it hasn't been freed */ if ( bus == NULL ) { return; } /* loop thru all slots */ for ( slotnum = 0 ; slotnum < NUM_SLOTS ; slotnum++ ) { /* check for anthing in slot */ if ( bus->slot_valid[slotnum] ) { /* point at slot data */ slot = &(bus->slot_data[slotnum]); /* We should check if this slot needs a latch strobe, but the docs aren't clear about master operation without auto-latching. So, we always latch the values for all boards, and never use master mode */ /* the check would be: if ( slot->strobe == 1 ) */ /* set the strobe bit, slave mode */ SelWrt(0x20, slot->slot_base + ENCRATE, slot->port_addr); /* repeat to guarantee at least 2uS */ SelWrt(0x20, slot->slot_base + ENCRATE, slot->port_addr); /* end of strobe pulse, stay in slave mode */ SelWrt(0x00, slot->slot_base + ENCRATE, slot->port_addr); /* fetch data from EPP to cache */ if ( slot->first_rd <= slot->last_rd ) { /* need to read some data */ n = slot->first_rd; eppaddr = slot->slot_base + slot->first_rd; /* read first byte */ slot->rd_buf[n++] = SelRead(eppaddr, slot->port_addr); /* read the rest */ while ( n <= slot->last_rd ) { slot->rd_buf[n++] = ReadMore(slot->port_addr); } } /* loop thru all functions associated with slot */ for ( functnum = 0 ; functnum < slot->num_rd_functs ; functnum++ ) { /* call function */ (slot->rd_functs[functnum])(slot); } } }}static void write_all(void *arg, long period){ bus_data_t *bus; slot_data_t *slot; int slotnum, functnum; unsigned char n, eppaddr; /* get pointer to bus data structure */ bus = *(bus_data_t **)(arg); /* test to make sure it hasn't been freed */ if ( bus == NULL ) { return; } /* loop thru all slots */ for ( slotnum = 0 ; slotnum < NUM_SLOTS ; slotnum++ ) { /* check for anthing in slot */ if ( bus->slot_valid[slotnum] ) { /* point at slot data */ slot = &(bus->slot_data[slotnum]); /* loop thru all functions associated with slot */ for ( functnum = 0 ; functnum < slot->num_wr_functs ; functnum++ ) { /* call function */ (slot->wr_functs[functnum])(slot); } /* write data from cache to EPP */ if ( slot->first_wr <= slot->last_wr ) { /* need to write some data */ n = slot->first_wr; eppaddr = slot->slot_base + slot->first_wr; /* write first byte */ SelWrt(slot->wr_buf[n++], eppaddr, slot->port_addr); /* write the rest */ while ( n <= slot->last_wr ) { WrtMore(slot->wr_buf[n++], slot->port_addr); } } } }}static void read_digins(slot_data_t *slot){ int b; unsigned char indata, mask; /* read the first 8 inputs */ indata = slot->rd_buf[UxC_DINA]; /* split the bits into 16 variables (8 regular, 8 inverted) */ b = 0; mask = 0x01; while ( b < 8 ) { *(slot->digin[b].data) = indata & mask; *(slot->digin[b].data_not) = !(indata & mask); mask <<= 1; b++; } /* read the next 8 inputs */ indata = slot->rd_buf[UxC_DINB]; /* and split them too */ mask = 0x01; while ( b < 16 ) { *(slot->digin[b].data) = indata & mask; *(slot->digin[b].data_not) = !(indata & mask); mask <<= 1; b++; }}static void write_digouts(slot_data_t *slot){ int b; unsigned char outdata, mask; outdata = 0x00; mask = 0x01; /* assemble output byte from 8 source variables */ for (b = 0; b < 8; b++) { /* get the data, add to output byte */ if ((*(slot->digout[b].data)) && (!slot->digout[b].invert)) { outdata |= mask; } if ((!*(slot->digout[b].data)) && (slot->digout[b].invert)) { outdata |= mask; } mask <<= 1; } /* write it to the hardware (cache) */ slot->wr_buf[UxC_DOUTA] = outdata;}static void read_encoders(slot_data_t *slot){ int i, byteindex; hal_u8_t mask = 0x01, indextemp; union pos_tag { signed long l; struct byte_tag { signed char b0; signed char b1; signed char b2; signed char b3; } byte; } pos, oldpos; indextemp = (hal_u8_t)(slot->rd_buf[ENCISR]); byteindex = ENCCNT0; /* first encoder count register */ for (i = 0; i < 4; i++) { oldpos.l = slot->encoder[i].oldreading; pos.byte.b0 = (signed char)slot->rd_buf[byteindex++]; pos.byte.b1 = (signed char)slot->rd_buf[byteindex++]; pos.byte.b2 = (signed char)slot->rd_buf[byteindex++]; pos.byte.b3 = oldpos.byte.b3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -