/* accel.c -- A character driver for a 2-axis accelerometer By Adam Rea, Travis Martin and Michael Goldschmidt */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #define ACCEL_DEV_MAJOR 23 #define ACCEL_IDENT "Accel Driver" #define ACCEL "Accel" #define FALSE 0 #define TRUE 1 #include #include unsigned long startX, elapsedX, startY, elapsedY; int x_count, y_count; unsigned long delay_flag; /* Our accelerometer interrupt routines */ /* Rising edge X */ void transX_up (int irq, void *dev_id, struct pt_regs *regs ) { startX = OSCR; return; } /* Rising edge Y */ void transY_up (int irq, void *dev_id, struct pt_regs *regs ) { startY = OSCR; return; } /* Falling edge X */ void transX_down (int irq, void *dev_id, struct pt_regs *regs ) { x_count = (x_count + 1)%5; if (x_count == 1) { elapsedX = OSCR - startX; } return; } /* Falling edge Y */ void transY_down (int irq, void *dev_id, struct pt_regs *regs ) { y_count = (y_count + 1)%5; if (y_count == 1) { elapsedY = OSCR - startY; } return; } /* Read routine ... returns an int in the form of a string to passed char* buffer. The top 16 bits of the int are the X Position (0 hard over right to 1023 hard over left) the bottom 16 bits are the Y Position (0 hard down to 1023 hard up) */ static ssize_t accel_read(struct file * file, char * buffer, size_t count, loff_t *ppos) { char temp_buffer[10]; unsigned long distance, xDist, yDist; distance = 0; if (elapsedY < 11456) { yDist = 0; } else if (elapsedY > 19411) { yDist = 1023; } else { yDist = ( (elapsedY - 11456) * 1024) / 7955; } if (elapsedX < 12251) { xDist = 0; } else if (elapsedX > 20524) { xDist = 1023; } else { xDist = ( (elapsedX - 12251) * 1024) / 8273; } distance = xDist; distance = distance << 16; distance = distance + yDist; sprintf(temp_buffer, "%d" , (int)distance); __copy_to_user((void*)buffer,(void*)temp_buffer,sizeof(char)*10); return 0; } /* Write unsupported */ static ssize_t accel_write(struct file* file, const char* buffer, size_t count, loff_t *ppos) { return -1; } /* get interrupts in open and setup ISRs */ int accel_open (struct inode* inode, struct file* file) { set_GPIO_IRQ_edge( GPIO_GPIO11, GPIO_RISING_EDGE ); set_GPIO_IRQ_edge( GPIO_GPIO12, GPIO_FALLING_EDGE ); set_GPIO_IRQ_edge( GPIO_GPIO13, GPIO_RISING_EDGE ); set_GPIO_IRQ_edge( GPIO_GPIO14, GPIO_FALLING_EDGE ); request_irq( IRQ_GPIO11, transX_up, 0, ACCEL , NULL ); request_irq( IRQ_GPIO12, transX_down, 0, ACCEL , NULL ); request_irq( IRQ_GPIO13, transY_up, 0, ACCEL , NULL ); request_irq( IRQ_GPIO14, transY_down, 0, ACCEL , NULL ); enable_irq( IRQ_GPIO11); enable_irq( IRQ_GPIO12); enable_irq( IRQ_GPIO13); enable_irq( IRQ_GPIO14); MOD_INC_USE_COUNT; return 0; } /* on close, release IRQ's */ int accel_release(struct inode* inode, struct file* file) { free_irq(IRQ_GPIO11, NULL); free_irq(IRQ_GPIO12, NULL); free_irq(IRQ_GPIO13, NULL); free_irq(IRQ_GPIO14, NULL); MOD_DEC_USE_COUNT; return 0; } static struct file_operations accel_file_ops = {NULL,NULL,accel_read,accel_write,NULL,NULL,NULL,NULL,accel_open, NULL, accel_release,NULL,NULL}; int init_module(void) { printk("<1>Loading %s ...\n", ACCEL_IDENT); if ( register_chrdev( ACCEL_DEV_MAJOR, ACCEL, &accel_file_ops ) ) { printk( "<1>%s, cannot register major device %d\n", ACCEL_IDENT, ACCEL_DEV_MAJOR ); return 1; } return 0; } void cleanup_module( void ) { unregister_chrdev( ACCEL_DEV_MAJOR, ACCEL ); printk( "unregistering 2 axis accelerometer device driver\n" ); }