📄 stepper.c
字号:
/* Copyright 1999 by Mark Whitis. All rights Reserved *//* Must be compiled with -O for outb to be inlined, otherwise *//* link error *//* Usermode: gcc -g -O -o teststep teststep.c *//* LKM: *//* gcc -O -DMODULE -D__KERNEL__ -o stepperout.o -c stepper.c *//* ld -r -o stepper.o stepperout.o ring.o */#include "stepper.h"#ifdef __KERNEL__ #include <linux/kernel.h> #include <linux/config.h> #ifdef MODULE #include <linux/module.h> #include <linux/version.h> #else /* Since the linux kernel is infected with the GNU Copyleft virus */ /* this code should not be statically linked with the kernel. */ #error This device driver must be compiled as a loadable kernel module #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT #endif #include <linux/types.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/errno.h> #include <asm/segment.h> #include <asm/io.h> #include <linux/sched.h> #include <linux/tqueue.h>#else #include <unistd.h> #include <stdlib.h> /* including stdio will cause grief */ #include <stdio.h> #include <asm/io.h>#endif#if 0 #include <stdarg.h> #include <ctype.h>#endif#include <string.h>#ifdef __KERNEL__ #include "ring.h" ring_buffer_t read_buffer; ring_buffer_t write_buffer; /* Parallel port interrupt to use for timing */ /* 0=use Linux 100hz jiffie timer */ static int irq = 0; /* Major device # to request */ static int major = 31; /* The device # we actually got */ static int stepper_major = 0; struct wait_queue *read_wait = NULL ; /* used to block user read if buffer underflow occurs */ struct wait_queue *write_wait = NULL; /* used to block user write if buffer overflow occurs */#endifstatic int debug = 1;static int verbose_io=0;static int verbose_move=0;static int base=0x378;static int power_down_on_exit=1;/* The following set the delay between steps */#ifndef __KERNEL__ static int delay = 50000; /* for usleep */ static int fastdelay = 0; /* delay loop */#else static int skipticks = 0;#endif/* the following value can be set to 0 to disable the *//* actual I/O operations. This will allow experimenting *//* on a system which does not have a free parallel port */static int do_io = 1;#ifdef __KERNEL__ static int read_is_sleeping = 0; static int write_is_sleeping = 0; static int abort_read = 0; static int abort_write = 0; static int read_is_open = 0; static int write_is_open = 0; static int interrupts_are_enabled = 0; static int autostart=1;#endifstatic int tick_counter=0;int xdest = 0;int xuser = 0;int xpos = 0;int ydest = 0;int yuser = 0;int ypos = 0;int zdest = 0;int zuser = 0;int zpos = 0;unsigned short word;void verbose_outb(int port, int value){ #ifndef __KERNEL__ if(verbose_io) printf("outb(%02X,%04X)\n",port,value); #else if(verbose_io) printk("outb(%02X,%04X)\n",port,value); #endif if(do_io) outb(port,value);}#ifdef __KERNEL__ void do_delay() { ; }#else void do_delay() { int i; if(fastdelay>0) { for(i=0;i<fastdelay;i++) { /* dummy operation so optimizer doesn't */ /* eliminate loop */ verbose_outb( (word&0x00FF),base+0); } } else { usleep(delay); } }#endifvoid report_status(){ char buf[128]; int rc; int i; int len; sprintf(buf,"x=%d,y=%d,z=%d,word=%08X\n",xpos,ypos,zpos,word); #ifdef __KERNEL__ len=strlen(buf); for(i=0;i<len;i++) { rc=ring_buffer_write(&read_buffer,&buf[i],1); } /* we need to wake up read function */ if(read_is_sleeping) { if(debug>=5) printk("stepper: waking up read/n"); wake_up_interruptible(&read_wait); } #else puts(buf); #endif }unsigned short x_steptable[8]= {0x0001,0x0005,0x0004,0x0006,0x0002,0x000A,0x0008,0x0009};unsigned short y_steptable[8]= {0x0010,0x0050,0x0040,0x0060,0x0020,0x00A0,0x0080,0x0090};unsigned short z_steptable[8]= {0x0100,0x0500,0x0400,0x0600,0x0200,0x0A00,0x0800,0x0900};unsigned short flipbits = 0x0B00;unsigned short irq_enable_bit=0x1000;void move_one_step(){ /* This is a very simple multiaxis move routine */ /* The axis will not move in a coordinate fashion */ /* unless the angle is a multiple of 45 degrees */ if(xdest > xpos) { xpos++; } else if(xdest < xpos) { xpos--; } if(ydest > ypos) { ypos++; } else if(ydest < ypos) { ypos--; } if(zdest > zpos) { zpos++; } else if(zdest < zpos) { zpos--; } word = x_steptable[xpos%8] | y_steptable[ypos%8] | z_steptable[zpos%8]; #ifdef __KERNEL__ if(interrupts_are_enabled) word |= irq_enable_bit; #endif /* Some of the signals are inverted */ word ^= flipbits; /* output low byte to data register */ verbose_outb( (word & 0x00FF), base+0); /* output high byte to control register */ verbose_outb( (word >> 8), base+2); if(verbose_move) report_status();}void move_all(){ while( (xpos!=xdest) || (ypos!=ydest) || (zpos!=zdest) ) { move_one_step(); do_delay(); }}void parse_one_char(char c){ static int value; static int dest=' '; static int negative=0; #if 0 c = toupper(c); #else if( (c>'a') && (c<'z') ) { c = c - 'a' + 'A'; } #endif switch(c) { case('X'): case('Y'): case('Z'): dest=c; break; case('='): break; case('-'): negative = !negative; break; case('+'): negative = 0; case('0'): case('1'): case('2'): case('3'): case('4'): case('5'): case('6'): case('7'): case('8'): case('9'): value *= 10; value += (c-'0'); break; case('?'): report_status(); case('\r'): case('\n'): case(','): if(negative) { value = -value; } if(dest=='X') { xuser = value; } else if(dest=='Y') { yuser = value; } else if(dest=='Z') { zuser = value; } value = 0; negative = 0; if( (c=='\n')||(c=='\r') ){ xdest = xuser; ydest = yuser; zdest = zuser; #ifdef __KERNEL__ if(debug>=3) { printk("xdest=%d ydest=%d zdest=%d\n", xdest,ydest,zdest); } #endif } break; }}#ifdef __KERNEL__ static int stepper_lseek(struct inode *inode, struct file *file, off_t offset, int orig) { /* Don't do anything, other than set offset to 0 */ return(file->f_pos=0); } static int stepper_read(struct inode *node, struct file *file, char *buf, int count) { static char message[] = "hello, world\n"; static char *p = message; int i; int rc; char xferbuf; int bytes_transferred; int newline_read; newline_read=0; if(!read_is_open) { printk("stepper: ERROR: stepper_read() called while " "not open for reading\n"); } bytes_transferred=0; if(debug>2) printk("stepper_read(%08X,%08X,%08X,%d)\n", node,file,buf,count); if(rc=verify_area(VERIFY_WRITE, buf, count) < 0 ) { printk("stepper_read(): verify area failed\n"); return(rc); } for(i=count; i>0; i--) { #if 0 if(!*p) p=message; put_fs_byte(*p++,buf++); #else while(1) { rc=ring_buffer_read(&read_buffer,&xferbuf,1); if(debug>3) { printk( "stepper: ring_buffer_read returned %d\n", rc); } if(rc==1) { bytes_transferred++; put_fs_byte(xferbuf,buf++); if(xferbuf=='\n') { printk("stepper_read(): newline\n"); newline_read=1; } break; /* read successful */ } read_is_sleeping=1; if(debug>=3) printk("stepper: read sleeping\n"); interruptible_sleep_on(&read_wait); read_is_sleeping=0; if(abort_read) return(bytes_transferred); } /* we want read to return at the end */ /* of each line */ if(newline_read) break; #endif } if(write_is_sleeping) wake_up_interruptible(&write_wait); if(debug>=3) { printk("stepper_read(): bytes=%d\n", bytes_transferred); } return(bytes_transferred); } static int stepper_write(struct inode *inode, struct file *file, const char *buf, int count) { int i; int rc; char xferbuf; int bytes_transferred; if(!write_is_open) { printk("stepper: ERROR: stepper_write() called" " while not open for writing\n"); } bytes_transferred=0; if(rc=verify_area(VERIFY_READ, buf, count) < 0 ) { return(rc); } for(i=count; i>0; i--) { xferbuf = get_fs_byte(buf++); while(1) { rc=ring_buffer_write(&write_buffer,&xferbuf,1); if(rc==1) { bytes_transferred++; break; } if(debug>10) printk("stepper: write sleeping\n"); write_is_sleeping=1; interruptible_sleep_on(&write_wait); write_is_sleeping=0; if(abort_write) return(bytes_transferred); } } if(read_is_sleeping) wake_up_interruptible(&read_wait); return(bytes_transferred); } void stepper_start() { /* do nothing at the moment */ } void stepper_stop() { /* do nothing at the moment */ } static int stepper_ioctl(struct inode *iNode, struct file *filePtr, unsigned int cmd, unsigned long arg) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -