/*
 * adxl.h
 *
 *  Created on: Jul 18, 2023
 *      Author: true
 */

#ifndef CODE_INC_ADXL_H_
#define CODE_INC_ADXL_H_



#include "hk32f030m.h"
#include "spi.h"



typedef struct adxl345_axes {
	int16_t x;
	int16_t y;
	int16_t z;
} adxl345_axes;



#define ADXL345_SPI_DEV					SPI1

#define ADXL345_SPI_CS_PORT				GPIOC
#define ADXL345_SPI_CS_PIN				GPIO_Pin_4

#define ADXL345_MODE_RD					0x80
#define ADXL345_MODE_WR					0x00
#define ADXL345_MODE_MB 				0x40	// multi-byte read or write

#define ADXL345_REG_DEVID 				0x00	// read-only, should == 0xE5
#define ADXL345_REG_THRESH_TAP 			0x1D 	// 0xff = 16g
#define ADXL345_REG_OFSX 				0x1E 	// 0x7f = 2g
#define ADXL345_REG_OFSY 				0x1F	// ""
#define ADXL345_REG_OFSZ 				0x20	// ""
#define ADXL345_REG_TAP_DUR 			0x21 	// 625usec/LSB, 0 disables
#define ADXL345_REG_TAP_LATENTCY 		0x22 	// 1.25ms/LSB, 0 disables double tap
#define ADXL345_REG_TAP_WINDOW 			0x23 	// 1.25ms/LSB, 0 disables double tap
#define ADXL345_REG_THRESH_ACT 			0x24 	// 0xFF = 16g
#define ADXL345_REG_THRESH_INACT 		0x25 	// 0xFF = 16g
#define ADXL345_REG_TIME_INACT 			0x26 	// 1sec/LSB
#define ADXL345_REG_ACT_INACT_CTL 		0x27
#define ADXL345_REG_THRESH_FF 			0x28 	// 0xFF = 16g, recommend 0x05-0x09
#define ADXL345_REG_TIME_FF 			0x29 	// 5ms/LSB, recommend 0x14-0x46
#define ADXL345_REG_TAP_AXES 			0x2A
#define ADXL345_REG_ACT_TAP_STATUS 		0x2B	// read-only
#define ADXL345_REG_BW_RATE 			0x2C
#define ADXL345_REG_POWER_CTL			0x2D
#define ADXL345_REG_INT_ENABLE 			0x2E
#define ADXL345_REG_INT_MAP 			0x2F
#define ADXL345_REG_INT_SOURCE 			0x30	// read-only
#define ADXL345_REG_DATA_FORMAT 		0x31
#define ADXL345_REG_DATAX0 				0x32	// read-only
#define ADXL345_REG_DATAX1 				0x33	// read-only
#define ADXL345_REG_DATAY0 				0x34	// read-only
#define ADXL345_REG_DATAY1 				0x35	// read-only
#define ADXL345_REG_DATAZ0 				0x36	// read-only
#define ADXL345_REG_DATAZ1 				0x37	// read-only
#define ADXL345_REG_FIFO_CTL 			0x38
#define ADXL345_REG_FIFO_STATUS 		0x39

#define ADXL345_TAP_AXES_X_ENABLE 		(1 << 2)
#define ADXL345_TAP_AXES_Y_ENABLE 		(1 << 1)
#define ADXL345_TAP_AXES_Z_ENABLE 		(1 << 0)

#define ADXL345_CTL_ACT_AC				(1 << 7)
#define ADXL345_CTL_ACT_X_ENA			(1 << 6)
#define ADXL345_CTL_ACT_Y_ENA			(1 << 5)
#define ADXL345_CTL_ACT_Z_ENA			(1 << 4)
#define ADXL345_CTL_INACT_AC			(1 << 3)
#define ADXL345_CTL_INACT_X_ENA			(1 << 2)
#define ADXL345_CTL_INACT_Y_ENA			(1 << 1)
#define ADXL345_CTL_INACT_Z_ENA			(1 << 0)

#define ADXL345_ACT_TAP_ACT_X 			(1 << 6)
#define ADXL345_ACT_TAP_ACT_Y 			(1 << 5)
#define ADXL345_ACT_TAP_ACT_Z 			(1 << 4)
#define ADXL345_ACT_TAP_TAP_X 			(1 << 2)
#define ADXL345_ACT_TAP_TAP_Y 			(1 << 1)
#define ADXL345_ACT_TAP_TAP_Z 			(1 << 0)

#define ADXL345_INT_DATA_READY			(1 << 7)
#define ADXL345_INT_SINGLE_TAP			(1 << 6)
#define ADXL345_INT_DOUBLE_TAP			(1 << 5)
#define ADXL345_INT_ACTIVITY			(1 << 4)
#define ADXL345_INT_INACTIVITY			(1 << 3)
#define ADXL345_INT_FREE_FALL			(1 << 2)
#define ADXL345_INT_WATERMARK			(1 << 1)
#define ADXL345_INT_OVERRUN				(1 << 0)
#define ADXL345_INT_ALL					0xff

#define ADXL345_DFMT_SELF_TEST			(1 << 7)
#define ADXL345_DFMT_SPI				(1 << 6)
#define ADXL345_DFMT_INT_INVERT			(1 << 5)
#define ADXL345_DFMT_FULL_RES			(1 << 3)
#define ADXL345_DFMT_JUSTIFY			(1 << 2)
#define ADXL345_DFMT_RANGE				(3 << 0)

#define ADXL345_INTR_ACTIVE_HI			1
#define ADXL345_INTR_ACTIVE_LO			0

#define ADXL345_BW_RATE_LOW_POWER 		(1 << 4)
#define ADXL345_BW_RATE_MASK 			(0xf)

#define ADXL345_BW_RATE_3200			0x0f
#define ADXL345_BW_RATE_1600			0x0e
#define ADXL345_BW_RATE_800				0x0d
#define ADXL345_BW_RATE_400				0x0c 	// low-power compat
#define ADXL345_BW_RATE_200				0x0b 	// low-power compat
#define ADXL345_BW_RATE_100				0x0a 	// low-power compat
#define ADXL345_BW_RATE_50				0x09 	// low-power compat
#define ADXL345_BW_RATE_25				0x08 	// low-power compat
#define ADXL345_BW_RATE_12_5			0x07 	// low-power compat
#define ADXL345_BW_RATE_6_25			0x06
#define ADXL345_BW_RATE_3_13			0x05
#define ADXL345_BW_RATE_1_56			0x04
#define ADXL345_BW_RATE_0_78			0x03
#define ADXL345_BW_RATE_0_39			0x02
#define ADXL345_BW_RATE_0_20			0x01
#define ADXL345_BW_RATE_0_10			0x00

#define ADXL345_POWER_CTL_LINK			(1 << 5)
#define ADXL345_POWER_CTL_AUTO_SLP 		(1 << 4)
#define ADXL345_POWER_CTL_MEASURE 		(1 << 3)
#define ADXL345_POWER_CTL_SLEEP 		(1 << 2)
#define ADXL345_POWER_CTL_WAKEUP_MASK 	(2 << 0)

#define ADXL345_POWER_CTL_WAKEUP_1HZ 	(0x03)
#define ADXL345_POWER_CTL_WAKEUP_2HZ 	(0x02)
#define ADXL345_POWER_CTL_WAKEUP_4HZ 	(0x01)
#define ADXL345_POWER_CTL_WAKEUP_8HZ 	(0x00)

#define ADXL345_DATA_FORMAT_SELF_TEST 	(1 << 7)
#define ADXL345_DATA_FORMAT_SPI 		(1 << 6)
#define ADXL345_DATA_FORMAT_INT_INV 	(1 << 5)
#define ADXL345_DATA_FORMAT_FULL_RES 	(1 << 3)
#define ADXL345_DATA_FORMAT_JUSTIFY		(1 << 2)
#define ADXL345_DATA_FORMAT_RANGE_MASK 	(2 << 0)

#define ADXL345_DATA_FORMAT_RANGE_16G 	(0x03)
#define ADXL345_DATA_FORMAT_RANGE_8G 	(0x03)
#define ADXL345_DATA_FORMAT_RANGE_4G 	(0x03)
#define ADXL345_DATA_FORMAT_RANGE_2G 	(0x03)

// r = receive buffer, t = transmit buffer, s = length
#define adxl_spi_xfer(r, t, s)			ADXL345_SPI_CS_PORT->BRR  = ADXL345_SPI_CS_PIN; \
										spi_mosi_sel(SPI_MOSI_SPI); \
										spi_xfer(t, r, s, 0); \
										ADXL345_SPI_CS_PORT->BSRR = ADXL345_SPI_CS_PIN;



extern adxl345_axes adxl;
extern adxl345_axes adxl_summing;
extern uint16_t movement_worst;



void adxl345_init();
void adxl345_tick();

void adxl345_get_axes(struct adxl345_axes *adxl);
int8_t adxl345_get_rotation(struct adxl345_axes *adxl);

int16_t adxl345_movement();

void adxl345_set_reg8(uint8_t reg, uint8_t val);

void adxl345_set_intr(uint8_t int2_map, uint8_t interrupt_flags);
void adxl345_set_intr_polarity(uint8_t active_polarity);
uint8_t adxl345_get_intr_flag();



#endif /* CODE_INC_ADXL_H_ */
