/*
 * bd3491.c
 *
 *  Created on: 20.10.2019
 *      Author: julian
 */

#include "bd3491.h"

// BD3491 driver
void bd_write_reg(I2C_HandleTypeDef * handle, uint8_t reg, uint8_t data) {
	uint8_t out[] = {
		reg,
		data
	};

	HAL_I2C_Master_Transmit(handle, 0b10000010, out, sizeof(out), HAL_MAX_DELAY);
}

void bd_set_input(I2C_HandleTypeDef * handle, uint8_t number) {
	if (number > 5) {
		return;
	}

	bd_write_reg(handle, 0x04, number);
}

#define BD_GAIN_TABLE(a) \
	a( 0, 0) \
	a( 2, 1) \
	a( 4, 2) \
	a( 6, 3) \
	a( 8, 4) \
	a(12, 6) \
	a(16, 8) \
	a(20, 10)

int bd_set_gain(I2C_HandleTypeDef * handle, uint8_t gain_in_db) {
	uint8_t regvalue = 0;
	if (gain_in_db > BD_MAX_GAIN) gain_in_db = BD_MAX_GAIN;

#define FINDREG(db, reg) if (gain_in_db <= db) { gain_in_db = db; regvalue = reg; } else
	BD_GAIN_TABLE(FINDREG) {
		// gain not in table (should not happen)
	}
#undef FINDREG

	bd_write_reg(handle, 0x06, regvalue<<1);
	return gain_in_db;
}

uint8_t bd_set_attenuation(I2C_HandleTypeDef * handle, uint8_t right_channel, uint8_t attenuation_in_db) {
	if ((attenuation_in_db&0x7F) > 87)
		attenuation_in_db = BD_INF_ATTENUATION;

	bd_write_reg(handle, 0x21 + right_channel, attenuation_in_db | 0x80);
	return attenuation_in_db;
}

// when gain == 0, cut bass boost
void bd_set_bass_boost(I2C_HandleTypeDef * handle, uint8_t gain) {
	bd_write_reg(handle, 0x51, (gain == 0)?(0x80):(0x00) | (gain&0x07) << 1);
}

// when gain == 0, cut treble boost
void bd_set_treble_boost(I2C_HandleTypeDef * handle, uint8_t gain) {
	bd_write_reg(handle, 0x57, (gain == 0)?(0x80):(0x00) | (gain&0x07) << 1);
}

void bd_set_sourround(I2C_HandleTypeDef * handle, enum BD_SOURROUND_GAIN gain) {
	uint8_t enable = (gain != BD_SOURROUND_OFF)?0x80:0;

	bd_write_reg(handle, 0x78, enable | gain);
}
