+/* errata usci30: only perform single reads
+ * second solution: use DMA
+ */
+void mw_acc_i2c_read(const uint8_t RegisterAddress, uint8_t *pData, const uint8_t Length)
+{
+ int i;
+
+ for ( i = 0; i < Length; i++ ) {
+ mw_acc_i2c_read_single(RegisterAddress + i, (pData + i));
+ }
+}
+
+
+void mw_acc_init(void)
+{
+ uint8_t WriteRegisterData;
+ uint8_t pReadRegisterData[4];
+#if defined MW_DEVBOARD_V2
+ char tstr[16];
+#endif
+
+ ENABLE_ACCELEROMETER_POWER();
+
+ mw_acc_init_i2c();
+
+ /*
+ * make sure part is in standby mode because some registers can only
+ * be changed when the part is not active.
+ */
+ WriteRegisterData = PC1_STANDBY_MODE;
+ mw_acc_i2c_write(KIONIX_CTRL_REG1, &WriteRegisterData, 1);
+
+ /* enable face-up and face-down detection */
+ WriteRegisterData = TILT_FDM | TILT_FUM;
+ mw_acc_i2c_write(KIONIX_CTRL_REG2, &WriteRegisterData, 1);
+
+ /*
+ * the interrupt from the accelerometer can be used to get periodic data
+ * the real time clock can also be used
+ */
+
+ /* change to output data rate to 25 Hz */
+ WriteRegisterData = WUF_ODR_25HZ | TAP_ODR_400HZ;
+ mw_acc_i2c_write(KIONIX_CTRL_REG3, &WriteRegisterData, 1);
+
+ /* enable interrupt and make it active high */
+ WriteRegisterData = IEN | IEA;
+ mw_acc_i2c_write(KIONIX_INT_CTRL_REG1, &WriteRegisterData, 1);
+
+ /* enable motion detection interrupt for all three axis */
+ WriteRegisterData = XBW | YBW | ZBW;
+ mw_acc_i2c_write(KIONIX_INT_CTRL_REG2, &WriteRegisterData, 1);
+
+ /* enable tap interrupt for Z-axis */
+ WriteRegisterData = TFDM;
+ mw_acc_i2c_write(KIONIX_INT_CTRL_REG3, &WriteRegisterData, 1);
+
+ /* set TDT_TIMER to 0.2 secs*/
+ WriteRegisterData = 0x50;
+ mw_acc_i2c_write(KIONIX_TDT_TIMER, &WriteRegisterData, 1);
+
+ /* set tap low and high thresholds (default: 26 and 182) */
+ WriteRegisterData = 40; //78;
+ mw_acc_i2c_write(KIONIX_TDT_L_THRESH, &WriteRegisterData, 1);
+ WriteRegisterData = 128;
+ mw_acc_i2c_write(KIONIX_TDT_H_THRESH, &WriteRegisterData, 1);
+
+ /* set WUF_TIMER counter */
+ WriteRegisterData = 10;
+ mw_acc_i2c_write(KIONIX_WUF_TIMER, &WriteRegisterData, 1);
+
+ /* this causes data to always be sent */
+ // WriteRegisterData = 0x00;
+ WriteRegisterData = 0x02 /*0x08*/;
+ mw_acc_i2c_write(KIONIX_WUF_THRESH, &WriteRegisterData, 1);
+
+ /* single byte read test */
+ mw_acc_i2c_read(KIONIX_DCST_RESP, pReadRegisterData, 1);
+#if defined MW_DEVBOARD_V2
+ snprintf(tstr, 16, "acc DCST 0x%02x\n", pReadRegisterData[0]);
+ debug_uart_tx(tstr);
+#endif
+
+ /* multiple byte read test */
+ mw_acc_i2c_read(KIONIX_WHO_AM_I, pReadRegisterData, 2);
+#if defined MW_DEVBOARD_V2
+ snprintf(tstr, 16, "acc is 0x%02x 0x%02x\n", pReadRegisterData[0], pReadRegisterData[1]);
+ debug_uart_tx(tstr);
+#endif
+
+ /*
+ * KIONIX_CTRL_REG3 and DATA_CTRL_REG can remain at their default values
+ *
+ * 50 Hz
+ */
+#if 0
+ /* KTXF9 300 uA; KTXI9 165 uA */
+ WriteRegisterData = PC1_OPERATING_MODE | TAP_ENABLE_TDTE;
+
+ /* 180 uA; KTXI9 115 uA */
+ WriteRegisterData = PC1_OPERATING_MODE | RESOLUTION_8BIT | WUF_ENABLE;
+
+ /* 180 uA; KTXI9 8.7 uA */
+ WriteRegisterData = PC1_OPERATING_MODE | TILT_ENABLE_TPE;
+
+ /* 720 uA; KTXI9 330 uA */
+ WriteRegisterData = PC1_OPERATING_MODE | RESOLUTION_12BIT | WUF_ENABLE;
+#endif
+
+ /* setup the default for the AccelerometerEnable command */
+#if 0
+ OperatingModeRegister = PC1_OPERATING_MODE | RESOLUTION_12BIT | TAP_ENABLE_TDTE | TILT_ENABLE_TPE; // | WUF_ENABLE;
+ InterruptControl = INTERRUPT_CONTROL_DISABLE_INTERRUPT;
+ SidControl = SID_CONTROL_SEND_DATA;
+ SidAddr = KIONIX_XOUT_L;
+ SidLength = XYZ_DATA_LENGTH;
+
+ AccelState = ACCEL_STATE_INIT;
+#endif
+}
+
+void mw_acc_enable(void)
+{
+ uint8_t sdata;
+
+ mw_acc_init();
+
+ sdata = PC1_OPERATING_MODE | RESOLUTION_12BIT | TAP_ENABLE_TDTE | TILT_ENABLE_TPE | WUF_ENABLE;
+ //sdata = PC1_OPERATING_MODE | RESOLUTION_8BIT | TAP_ENABLE_TDTE | TILT_ENABLE_TPE; // | WUF_ENABLE;
+ mw_acc_i2c_write(KIONIX_CTRL_REG1, &sdata, 1);
+
+ ACCELEROMETER_INT_ENABLE();
+ mw_acc_i2c_read(KIONIX_INT_REL, &sdata, 1);
+ AccelState = ACCEL_STATE_ENABLED;
+}
+
+void mw_acc_disable(void)
+{
+ uint8_t sdata;
+
+ if (AccelState == ACCEL_STATE_ENABLED) {
+ sdata = PC1_STANDBY_MODE;
+ mw_acc_i2c_write(KIONIX_CTRL_REG1, &sdata, 1);
+
+ ACCELEROMETER_INT_DISABLE();
+ mw_acc_disable_i2c();
+ DISABLE_ACCELEROMETER_POWER();
+ AccelState = ACCEL_STATE_DISABLED;
+ }
+}
+
+void mw_acc_read(int16_t *x, int16_t *y, int16_t *z)
+{
+ uint8_t rdata[6];
+
+ if (AccelState == ACCEL_STATE_ENABLED) {
+ mw_acc_i2c_read(KIONIX_XOUT_L, rdata, 6);
+
+ *x = rdata[0] | (rdata[1] << 8);
+ *y = rdata[2] | (rdata[3] << 8);
+ *z = rdata[4] | (rdata[5] << 8);
+ } else {
+ *x = 0;
+ *y = 0;
+ *z = 0;
+ }
+}
+
+void mw_acc_handle_irq(void)
+{
+ uint8_t sdata, srcreg1, srcreg2;
+#if defined MW_DEVBOARD_V2
+ char tstr[16];
+#endif
+
+ mw_acc_i2c_read(KIONIX_INT_SRC_REG1, &srcreg1, 1);
+#if defined MW_DEVBOARD_V2
+ snprintf(tstr, 16, "accsrc1: 0x%02x\n", srcreg1);
+ debug_uart_tx(tstr);
+#endif
+ mw_acc_i2c_read(KIONIX_INT_SRC_REG2, &srcreg2, 1);
+#if defined MW_DEVBOARD_V2
+ snprintf(tstr, 16, "accsrc2: 0x%02x\n", srcreg2);
+ debug_uart_tx(tstr);
+#endif
+ if (srcreg1 & INT_TAP_SINGLE) {
+ };
+ if (srcreg1 & INT_TAP_DOUBLE) {
+ };
+ if (srcreg2 & INT_WUFS) {
+ int16_t x, y, z;
+ mw_acc_read(&x, &y, &z);
+ oswald_handle_accel_event((int8_t)(x / (32768 / 255)), (int8_t)(y / (32768 / 255)), (int8_t)(z / (32768 / 255)));
+ }
+
+ mw_acc_i2c_read(KIONIX_INT_REL, &sdata, 1);
+}