void bma020_chip_init(void) { /*assign register memory to bma020 object */ bma020.image = &bma020regs; bma020.bma020_bus_write = i2c_acc_bma020_write; bma020.bma020_bus_read = i2c_acc_bma020_read; #ifdef CONFIG_HAS_EARLYSUSPEND bma020.early_suspend.suspend = bma020_early_suspend; bma020.early_suspend.resume = bma020_late_resume; register_early_suspend(&bma020.early_suspend); #endif /*call init function to set read write functions, read registers */ bma020_init( &bma020 ); /* from this point everything is prepared for sensor communication */ /* set range to 2G mode, other constants: * 4G: BMA020_RANGE_4G, * 8G: BMA020_RANGE_8G */ bma020_set_range(BMA020_RANGE_2G); /* set bandwidth to 25 HZ */ bma020_set_bandwidth(BMA020_BW_25HZ); /* for interrupt setting */ // bma020_set_low_g_threshold( BMA020_HG_THRES_IN_G(0.35, 2) ); // bma020_set_interrupt_mask( BMA020_INT_LG ); }
/** * @brief BMA020 ioctl control entry point * * * @param hal Address of an initialized sensor device descriptor. * @param cmd Command to execute * @param arg Argument for command (varies) * @return bool true if the call succeeds, else false is returned. */ static bool bma020_ioctl(sensor_t *sensor, sensor_command_t cmd, void *arg) { sensor_hal_t *const hal = sensor->hal; sensor_data_t sample = {.scaled = true}; switch (cmd) { case SENSOR_SET_RANGE: return bma020_set_range(hal, *((uint16_t *)arg)); case SENSOR_SET_BANDWIDTH: return bma020_set_bandwidth(hal, *((uint16_t *)arg)); case SENSOR_READ_VECTOR: if (bma020_get_accel(hal, &sample)) { vector3_t *const pvec = (vector3_t *)arg; pvec->x = sample.axis.x; pvec->y = sample.axis.y; pvec->z = sample.axis.z; return true; } else { return false; } default: sensor->err = SENSOR_ERR_UNSUPPORTED; return false; } }
static ssize_t bma020_show_accel_value(struct device *dev,struct device_attribute *attr, char *buf) { bma020acc_t accel; bma020_set_mode(BMA020_MODE_NORMAL); bma020_set_range(BMA020_RANGE_2G); bma020_set_bandwidth(BMA020_BW_100HZ); bma020_read_accel_xyz( &accel); return sprintf(buf, "%d,%d,%d\n", accel.x,accel.y,accel.z); }
int bma020_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; unsigned char data[6]; /* check cmd */ if(_IOC_TYPE(cmd) != BMA150_IOC_MAGIC) { #if DEBUG printk("cmd magic type error\n"); #endif return -ENOTTY; } if(_IOC_NR(cmd) > BMA150_IOC_MAXNR) { #if DEBUG printk("cmd number error\n"); #endif return -ENOTTY; } if(_IOC_DIR(cmd) & _IOC_READ) err = !access_ok(VERIFY_WRITE,(void __user*)arg, _IOC_SIZE(cmd)); else if(_IOC_DIR(cmd) & _IOC_WRITE) err = !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd)); if(err) { #if DEBUG printk("cmd access_ok error\n"); #endif return -EFAULT; } #if 0 /* check bam150_client */ if( bma150_client == NULL) { #if DEBUG printk("I2C driver not install\n"); #endif return -EFAULT; } #endif switch(cmd) { case BMA150_READ_ACCEL_XYZ: err = bma020_read_accel_xyz((bma020acc_t*)data); if(copy_to_user((bma020acc_t*)arg,(bma020acc_t*)data,6)!=0) { #if DEBUG printk("copy_to error\n"); #endif return -EFAULT; } return err; case BMA150_SET_RANGE: if(copy_from_user(data,(unsigned char*)arg,1)!=0) { #if DEBUG printk("[BMA150] copy_from_user error\n"); #endif return -EFAULT; } err = bma020_set_range(*data); return err; case BMA150_SET_MODE: if(copy_from_user(data,(unsigned char*)arg,1)!=0) { #if DEBUG printk("[BMA150] copy_from_user error\n"); #endif return -EFAULT; } err = bma020_set_mode(*data); return err; case BMA150_SET_BANDWIDTH: if(copy_from_user(data,(unsigned char*)arg,1)!=0) { #if DEBUG printk("[BMA150] copy_from_user error\n"); #endif return -EFAULT; } err = bma020_set_bandwidth(*data); return err; default: return 0; } }
int bma020_calibrate(bma020acc_t orientation, int *tries) { unsigned short offset_x, offset_y, offset_z; unsigned short old_offset_x, old_offset_y, old_offset_z; unsigned short changed_offset_x, changed_offset_y, changed_offset_z; int need_calibration=0, min_max_ok=0; int ltries; int retry = 30; bma020acc_t min,max,avg; printk("[%s] +\n", __func__); bma020_set_range(BMA020_RANGE_2G); bma020_set_bandwidth(BMA020_BW_25HZ); bma020_set_ee_w(1); bma020_get_offset(0, &offset_x); bma020_get_offset(1, &offset_y); bma020_get_offset(2, &offset_z); old_offset_x = offset_x; old_offset_y = offset_y; old_offset_z = offset_z; ltries = *tries; printk("[%s] old offset_x = %d, offset_y = %d, offset_z = %d\n", __func__, old_offset_x, offset_y, offset_z); orientation.x = 0; orientation.y = 0; orientation.z = 1; do { bma020_read_accel_avg(10, &min, &max, &avg); /* read acceleration data min, max, avg */ min_max_ok = bma020_verify_min_max(min, max, avg); if(!min_max_ok) { retry--; if(retry <= 0) return (-1); } /* check if calibration is needed */ if (min_max_ok) need_calibration = bma020_calc_new_offset(orientation, avg, &offset_x, &offset_y, &offset_z); if (*tries==0) /*number of maximum tries reached? */ break; if (need_calibration) { /* when needed calibration is updated in image */ printk("[%s] need calibration. tries = %d. changed offset x = %d, y = %d, z = %d\n", __func__, *tries, offset_x, offset_y, offset_z); (*tries)--; bma020_set_offset(0, offset_x); bma020_set_offset(1, offset_y); bma020_set_offset(2, offset_z); bma020_pause(20); } printk("\n"); } while (need_calibration || !min_max_ok); if (*tries>0 && *tries < ltries) { printk("[%s] eeprom is updated. new offset x=%d, y=%d, z=%d\n", __func__, offset_x, offset_y, offset_z); if (old_offset_x!= offset_x) bma020_set_offset_eeprom(0, offset_x); if (old_offset_y!= offset_y) bma020_set_offset_eeprom(1,offset_y); if (old_offset_z!= offset_z) bma020_set_offset_eeprom(2, offset_z); } printk("[%s] tries = %d\n", __func__, *tries); bma020_set_ee_w(0); bma020_pause(20); *tries = ltries - *tries; printk("[%s] -\n", __func__); return !need_calibration; }
/** * @brief Bosch BMA020 accelerometer driver initialization. * * This is the main initialization function for the BMA020 device. * The accelerometer range and bandwidth are set based on user-specified * values from the system configuration. * * @param sensor Address of a sensor device descriptor. * @param resvd Reserved value. * @return bool true if the call succeeds, else false is returned. */ bool bma020_init(sensor_t *sensor, int resvd) { bool status = false; sensor_hal_t *const hal = sensor->hal; if (BMA020_ID_VAL == sensor_bus_get(hal, BMA020_CHIP_ID)) { /* Set the driver function table and capabilities pointer. */ static const sensor_device_t bma020_device = { .func.read = bma020_read, .func.ioctl = bma020_ioctl, .caps.feature = SENSOR_CAPS_3_AXIS | SENSOR_CAPS_SELFTEST | SENSOR_CAPS_HI_G_EVENT | SENSOR_CAPS_LO_G_EVENT, .caps.vendor = SENSOR_VENDOR_BOSCH, .caps.range_table = range_table, .caps.band_table = band_table, .caps.range_count = ARRAYSIZE(range_table), .caps.band_count = ARRAYSIZE(band_table), .caps.units = SENSOR_UNITS_g0, .caps.scale = SENSOR_SCALE_milli, .caps.name = "BMA020 Digital, triaxial acceleration sensor" }; sensor->drv = &bma020_device; /* Set the driver (device) default range, bandwidth, and * resolution. */ hal->range = 2000; /* milli-g */ hal->bandwidth = 25; /* Hertz */ hal->resolution = BMA020_DATA_RESOLUTION; bma020_set_range(hal, 0); bma020_set_bandwidth(hal, 0); /* Set the device burst read base address. */ hal->burst_addr = BMA020_ACC_X_LSB; status = (STATUS_OK == hal->bus.status); } return status; } /** * @brief Read accelerometer device ID and revision numbers. * * This function reads the accelerometer hardware identification registers * and returns these values in the specified data structure. * * @param hal Address of an initialized sensor hardware descriptor. * @param data Address of sensor_data_t structure to return values. * @return bool true if the call succeeds, else false is returned. */ static bool bma020_device_id(sensor_hal_t *hal, sensor_data_t *data) { data->device.id = sensor_bus_get(hal, BMA020_CHIP_ID); data->device.version = sensor_bus_get(hal, BMA020_CHIP_VERSION); return true; }