/*
 * This file is part of the libopencm3 project.
 *
 * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
 * Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
 * Modified by Fernando Cortes <fermando.corcam@gmail.com>
 * modified by Guillermo Rivera <memogrg@gmail.com>
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/stm32/gpio.h>

#define LDGreen GPIOG, GPIO13
#define LDRed GPIOG, GPIO14 

static void i2c_setup(void)
{
	rcc_periph_clock_enable(RCC_I2C3);
	rcc_periph_clock_enable(RCC_GPIOA);
	rcc_periph_clock_enable(RCC_GPIOC);
	/*rcc_set_i2c_clock_hsi(I2C3);   No es necesario porque ya estan activados en arriba */

/* Se cambian los pines del protocolo i2c a los pines qe corresponden al touch-screen del F429  */

	i2c_reset(I2C3);
	/* Setup GPIO pin GPIO_USART2_TX/GPIO9 on GPIO port A for transmit. */
	gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8);
	gpio_set_af(GPIOA, GPIO_AF4, GPIO8);

/* Casualmente los alternate functions son los mismos que el F3 para cada uno de los pines del i2c*/

	/* Setup GPIO pin GPIO_USART2_TX/GPIO9 on GPIO port A for transmit. */
	gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);
	gpio_set_af(GPIOB, GPIO_AF4, GPIO9);

	i2c_peripheral_disable(I2C3);

  



/* Configuraciones básicas del i2c */

	//configure ANFOFF DNF[3:0] in CR1
	/* i2c_enable_analog_filter(I2C3);  vamos a no implementarlas */
	/*i2c_set_digital_filter(I2C3, I2C_CR1_DNF_DISABLED); */
	//Configure PRESC[3:0] SDADEL[3:0] SCLDEL[3:0] SCLH[7:0] SCLL[7:0]
	// in TIMINGR
	i2c_100khz_i2cclk8mhz(I2C3);
	//configure No-Stretch CR1 (only relevant in slave mode)
	i2c_enable_stretching(I2C3);
	//addressing mode
	i2c_set_7bit_addr_mode(I2C3);
	i2c_peripheral_enable(I2C3);
}




 /* ¡¡¡¡¡¡¡¡¡¡¡¡¡MARCADOR!!!!!!!!!!! */

static void usart_setup(void)
{
	/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
	rcc_periph_clock_enable(RCC_USART1);
	rcc_periph_clock_enable(RCC_GPIOA);

	/* Setup GPIO pin GPIO_USART2_TX/GPIO9 on GPIO port A for transmit. */
	gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO10);
	gpio_set_af(GPIOA, GPIO_AF7, GPIO9| GPIO10);

	/* Setup UART parameters. */
	usart_set_baudrate(USART1, 115200);
	usart_set_databits(USART1, 8);
	usart_set_stopbits(USART1, USART_STOPBITS_1);
	usart_set_mode(USART1, USART_MODE_TX_RX);
	usart_set_parity(USART1, USART_PARITY_NONE);
	usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);

	/* Finally enable the USART. */
	usart_enable(USART1);
}

static void gpio_setup(void)
{
	rcc_periph_clock_enable(RCC_GPIOG);
	gpio_mode_setup(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO13 |
		GPIO14);
}

static void my_usart_print_int(uint32_t usart, int32_t value)
{
	int8_t i;
	int8_t nr_digits = 0;
	char buffer[25];

	if (value < 0) {
		usart_send_blocking(usart, '-');
		value = value * -1;
	}

	if (value == 0) {
		usart_send_blocking(usart, '0');
	}

	while (value > 0) {
		buffer[nr_digits++] = "0123456789"[value % 10];
		value /= 10;
	}

	for (i = nr_digits-1; i >= 0; i--) {
		usart_send_blocking(usart, buffer[i]);
	}

	usart_send_blocking(usart, '\r');
	usart_send_blocking(usart, '\n');
}

static void clock_setup(void)
{
	rcc_clock_setup_hsi(&hsi_16mhz[CLOCK_64MHZ]);   /* hacer un grep en el directorio f4  si no funciona*/  
}

#define I2C_ACC_ADDR 0x19
#define I2C_MAG_ADDR 0x1E
#define ACC_STATUS 0x27
#define ACC_CTRL_REG1_A 0x20
#define ACC_CTRL_REG1_A_ODR_SHIFT 4
#define ACC_CTRL_REG1_A_ODR_MASK 0xF
#define ACC_CTRL_REG1_A_XEN (1 << 0)
#define ACC_CTRL_REG4_A 0x23

#define ACC_OUT_X_L_A 0x28
#define ACC_OUT_X_H_A 0x29l

//      gpio_port_write(GPIOE, (I2C_ISR(i2c) & 0xFF) << 8);
//      my_usart_print_int(USART2, (I2C_ISR(i2c) & 0xFF));

int main(void)
{
	clock_setup();
	gpio_setup();
	usart_setup();
	i2c_setup();
	/*uint8_t data[1]={(0x4 << ACC_CTRL_REG1_A_ODR_SHIFT) | ACC_CTRL_REG1_A_XEN};*/
	uint8_t data[1]={0x97};
	write_i2c(I2C3, I2C_ACC_ADDR, ACC_CTRL_REG1_A, 1, data);
	data[0]=0x08;
	write_i2c(I2C3, I2C_ACC_ADDR, ACC_CTRL_REG4_A, 1, data);
	uint16_t acc_x;

	while (1) {

		read_i2c(I2C3, I2C_ACC_ADDR, ACC_STATUS, 1, data);
		/*my_usart_print_int(USART2, data[0]);*/
		read_i2c(I2C3, I2C_ACC_ADDR, ACC_OUT_X_L_A, 1, data);
		acc_x=data[0];
		read_i2c(I2C3, I2C_ACC_ADDR, ACC_OUT_X_H_A, 1, data);
		acc_x|=(data[0] << 8);
		my_usart_print_int(USART2, (int16_t) acc_x);
		//int i;
		//for (i = 0; i < 800000; i++)    /* Wait a bit. */
		//  __asm__("nop");
	}

	return 0;
}

