From 115b771e56aba7e7d066c8a58819d61d51009116 Mon Sep 17 00:00:00 2001
From: Karl Palsson <karlp@tweak.net.au>
Date: Tue, 21 Feb 2017 21:37:36 +0000
Subject: i2c: Initial stub import of old f4 code

Currently (despite docs) is an import of code reading the onboard i2c
peripheral
---
 tests/i2c-master/Makefile.stm32f4-disco |  40 +++++++
 tests/i2c-master/README.md              |  17 +++
 tests/i2c-master/main-stm32f4-disco.c   | 189 ++++++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+)
 create mode 100644 tests/i2c-master/Makefile.stm32f4-disco
 create mode 100644 tests/i2c-master/README.md
 create mode 100644 tests/i2c-master/main-stm32f4-disco.c

(limited to 'tests')

diff --git a/tests/i2c-master/Makefile.stm32f4-disco b/tests/i2c-master/Makefile.stm32f4-disco
new file mode 100644
index 0000000..8621f2f
--- /dev/null
+++ b/tests/i2c-master/Makefile.stm32f4-disco
@@ -0,0 +1,40 @@
+##
+## This file is part of the libopencm3 project.
+##
+## 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/>.
+##
+
+BOARD = stm32f4-disco
+PROJECT = i2c-master-$(BOARD)
+BUILD_DIR = bin-$(BOARD)
+
+SHARED_DIR = ../../shared
+
+CFILES = main-$(BOARD).c
+#CFILES += adc-power.c
+CFILES += trace.c trace_stdio.c
+
+VPATH += $(SHARED_DIR)
+
+INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
+
+OPENCM3_DIR=../../libopencm3/
+
+### This section can go to an arch shared rules eventually...
+DEVICE=stm32f405xg
+#OOCD_INTERFACE = stlink-v2
+#OOCD_TARGET = stm32f4x
+OOCD_FILE = ../../openocd/openocd.stm32f4-disco.cfg
+
+include ../../rules.mk
diff --git a/tests/i2c-master/README.md b/tests/i2c-master/README.md
new file mode 100644
index 0000000..74acefb
--- /dev/null
+++ b/tests/i2c-master/README.md
@@ -0,0 +1,17 @@
+i2c master mode tests.
+
+While many of the disco boards have some form of i2c device onboard,
+which would, on the face of it, make testing easy, it's a different
+device on each board, and there are boards without it.
+
+Instead, use a known I2C peripheral on all boards, and require/expect
+a known fixed i2c slave device.  (Eventually, this will be a soft
+controllable i2c slave in the auto test setup ;)
+
+Debug is via SWO wherever possible, PA2 (tx only) on less capable cores
+
+Pinouts:
+
+board		SCLK	SDA
+f4-disco	PB8	PB9	i2c1
+
diff --git a/tests/i2c-master/main-stm32f4-disco.c b/tests/i2c-master/main-stm32f4-disco.c
new file mode 100644
index 0000000..c74b5eb
--- /dev/null
+++ b/tests/i2c-master/main-stm32f4-disco.c
@@ -0,0 +1,189 @@
+/*
+ * Feb 2017 Karl Palsson <karlp@tweak.net.au>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/rcc.h>
+
+#include "trace.h"
+
+#define LED_DISCO_GREEN_PORT GPIOD
+#define LED_DISCO_GREEN_PIN GPIO12
+
+#define CODEC_ADDRESS 0x4a
+
+
+static void codec_gpio_init(void)
+{
+	/* reset pin */
+	rcc_periph_clock_enable(RCC_GPIOD);
+	gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);
+
+	/* i2c control lines */
+	rcc_periph_clock_enable(RCC_GPIOB);
+	gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6 | GPIO9);
+	gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO6 | GPIO9);
+	gpio_set_af(GPIOB, GPIO_AF4, GPIO6 | GPIO9);
+}
+
+static void codec_i2c_init(void)
+{
+	rcc_periph_clock_enable(RCC_I2C1);
+	i2c_peripheral_disable(I2C1);
+	i2c_reset(I2C1);
+	i2c_set_standard_mode(I2C1);
+	i2c_enable_ack(I2C1);
+	i2c_set_dutycycle(I2C1, I2C_CCR_DUTY_DIV2); /* default, no need to do this really */
+	i2c_set_clock_frequency(I2C1, I2C_CR2_FREQ_42MHZ);
+	/* 42MHz / (100kHz * 2) */
+	i2c_set_ccr(I2C1, 210);
+	/* standard mode, freqMhz+1*/
+	i2c_set_trise(I2C1, 43);
+	i2c_peripheral_enable(I2C1);
+}
+
+static void codec_init(void)
+{
+	int i;
+	/* Configure the Codec related IOs */
+	codec_gpio_init();
+
+	/* reset the codec */
+	gpio_clear(GPIOD, GPIO4);
+	for (i = 0; i < 1000000; i++) { /* Wait a bit. */
+		__asm__("NOP");
+	}
+	gpio_set(GPIOD, GPIO4);
+
+	codec_i2c_init();
+}
+
+static int codec_write_reg(uint8_t reg, uint8_t val)
+{
+	uint32_t i2c = I2C1;
+
+	while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
+	}
+
+	i2c_send_start(i2c);
+
+	/* Wait for master mode selected */
+	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
+		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
+
+	i2c_send_7bit_address(i2c, CODEC_ADDRESS, I2C_WRITE);
+
+	/* Waiting for address is transferred. */
+	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
+
+	/* Cleaning ADDR condition sequence. */
+	uint32_t reg32 = I2C_SR2(i2c);
+	(void) reg32; /* unused */
+
+	/* Common above here */
+
+	/* Sending the data. */
+	i2c_send_data(i2c, reg);
+	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
+	i2c_send_data(i2c, val);
+	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));
+
+	/* Send STOP condition. */
+	i2c_send_stop(i2c);
+	return 0;
+}
+
+static uint32_t codec_read_reg(uint8_t reg)
+{
+	uint32_t i2c = I2C1;
+
+	while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
+	}
+
+	i2c_send_start(i2c);
+
+	/* Wait for master mode selected */
+	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
+		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
+
+	i2c_send_7bit_address(i2c, CODEC_ADDRESS, I2C_WRITE);
+
+	/* Waiting for address is transferred. */
+	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
+
+	/* Cleaning ADDR condition sequence. */
+	uint32_t reg32 = I2C_SR2(i2c);
+	(void) reg32; /* unused */
+
+	/*  Common stuff ABOVE HERE     */
+
+	i2c_send_data(i2c, reg);
+	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
+
+	i2c_send_start(i2c);
+
+	/* Wait for master mode selected */
+	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
+		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
+
+	i2c_send_7bit_address(i2c, CODEC_ADDRESS, I2C_READ);
+
+	/* Waiting for address is transferred. */
+	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
+
+	i2c_disable_ack(i2c);
+
+	/* Cleaning ADDR condition sequence. */
+	reg32 = I2C_SR2(i2c);
+	(void) reg32; /* unused */
+
+	i2c_send_stop(i2c);
+
+	while (!(I2C_SR1(i2c) & I2C_SR1_RxNE));
+	uint32_t result = i2c_get_data(i2c);
+
+	i2c_enable_ack(i2c);
+	I2C_SR1(i2c) &= ~I2C_SR1_AF;
+	return result;
+}
+
+static void codec_readid(void)
+{
+	uint8_t res = codec_read_reg(0x01);
+	printf("raw res = %#x Codec is %#x (should be 0x1c), revision %d\n", res, res >> 3, res & 0x7);
+}
+
+int main(void)
+{
+	int i, j;
+	rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
+	/* green led for ticking */
+	rcc_periph_clock_enable(RCC_GPIOD);
+	gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
+		LED_DISCO_GREEN_PIN);
+	printf("hi guys!\n");
+	codec_init();
+	codec_readid();
+
+	codec_write_reg(0x14, 0xff);
+	for (i = 0; i < 8; i++) {
+		uint8_t pass_vol_a = codec_read_reg(0x14);
+		printf("Passthrough vol A was: %#x\n", pass_vol_a);
+		codec_write_reg(0x14, pass_vol_a >> 1);
+		gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
+		for (j = 0; j < 100000; j++) { /* Wait a bit. */
+			__asm__("NOP");
+		}
+	}
+
+	/* Nothing else to do */;
+	while (1) {
+		;
+	}
+	return 0;
+}
-- 
cgit