Skip to content
Snippets Groups Projects
Commit 6f08f8ce authored by Damien's avatar Damien
Browse files

Add working MMA support.

parent d2c1a732
Branches
No related tags found
No related merge requests found
...@@ -319,6 +319,10 @@ static bool fit_small_int(py_small_int_t o) { ...@@ -319,6 +319,10 @@ static bool fit_small_int(py_small_int_t o) {
return true; return true;
} }
py_obj_t py_obj_new_int(int value) {
return TO_SMALL_INT(value);
}
py_obj_t py_obj_new_const(const char *id) { py_obj_t py_obj_new_const(const char *id) {
py_obj_base_t *o = m_new(py_obj_base_t, 1); py_obj_base_t *o = m_new(py_obj_base_t, 1);
o->kind = O_CONST; o->kind = O_CONST;
......
...@@ -99,6 +99,7 @@ void py_obj_print(py_obj_t o); ...@@ -99,6 +99,7 @@ void py_obj_print(py_obj_t o);
int rt_is_true(py_obj_t arg); int rt_is_true(py_obj_t arg);
int py_get_int(py_obj_t arg); int py_get_int(py_obj_t arg);
qstr py_get_qstr(py_obj_t arg); qstr py_get_qstr(py_obj_t arg);
py_obj_t py_obj_new_int(int value);
py_obj_t rt_load_const_str(qstr qstr); py_obj_t rt_load_const_str(qstr qstr);
py_obj_t rt_load_name(qstr qstr); py_obj_t rt_load_name(qstr qstr);
py_obj_t rt_load_global(qstr qstr); py_obj_t rt_load_global(qstr qstr);
......
...@@ -433,6 +433,24 @@ py_obj_t pyb_servo_set(py_obj_t value) { ...@@ -433,6 +433,24 @@ py_obj_t pyb_servo_set(py_obj_t value) {
return py_const_none; return py_const_none;
} }
#define MMA_ADDR (0x4c)
py_obj_t pyb_mma_read() {
mma_start(MMA_ADDR, 1);
mma_send_byte(0);
mma_restart(MMA_ADDR, 0);
py_obj_t data[4];
for (int i = 3; i >= 1; i--) {
int v = mma_read_ack() & 0x3f;
if (v & 0x20) {
v |= ~0x1f;
}
data[i] = py_obj_new_int(v);
}
data[0] = py_obj_new_int(mma_read_nack());
return rt_build_tuple(4, data); // items in reverse order in data
}
int main(void) { int main(void) {
// TODO disable JTAG // TODO disable JTAG
...@@ -480,6 +498,7 @@ soft_reset: ...@@ -480,6 +498,7 @@ soft_reset:
rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led)); rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw)); rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw));
rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_1(pyb_servo_set)); rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_1(pyb_servo_set));
rt_store_attr(m, qstr_from_str_static("mma"), rt_make_function_0(pyb_mma_read));
rt_store_name(qstr_from_str_static("pyb"), m); rt_store_name(qstr_from_str_static("pyb"), m);
} }
...@@ -554,6 +573,62 @@ soft_reset: ...@@ -554,6 +573,62 @@ soft_reset:
// USB // USB
usb_init(); usb_init();
// MMA
{
// init and reset address to zero
mma_init();
mma_start(MMA_ADDR, 1);
mma_send_byte(0);
mma_stop();
/*
// read and print all 11 registers
mma_start(MMA_ADDR, 1);
mma_send_byte(0);
mma_restart(MMA_ADDR, 0);
for (int i = 0; i <= 0xa; i++) {
int data;
if (i == 0xa) {
data = mma_read_nack();
} else {
data = mma_read_ack();
}
printf(" %02x", data);
}
printf("\n");
*/
// put into active mode
mma_start(MMA_ADDR, 1);
mma_send_byte(7); // mode
mma_send_byte(1); // active mode
mma_stop();
/*
// infinite loop to read values
for (;;) {
sys_tick_delay_ms(500);
mma_start(MMA_ADDR, 1);
mma_send_byte(0);
mma_restart(MMA_ADDR, 0);
for (int i = 0; i <= 3; i++) {
int data;
if (i == 3) {
data = mma_read_nack();
printf(" %02x\n", data);
} else {
data = mma_read_ack() & 0x3f;
if (data & 0x20) {
data |= ~0x1f;
}
printf(" % 2d", data);
}
}
}
*/
}
// turn boot-up LED off // turn boot-up LED off
led_state(PYB_LED_G1, 0); led_state(PYB_LED_G1, 0);
...@@ -737,60 +812,6 @@ soft_reset: ...@@ -737,60 +812,6 @@ soft_reset:
led_state(PYB_LED_G1, 0); led_state(PYB_LED_G1, 0);
} }
// MMA testing
if (0) {
printf("1");
mma_init();
printf("2");
mma_start(0x4c, 1);
printf("3");
mma_send_byte(0);
printf("4");
mma_stop();
printf("5");
mma_start(0x4c, 1);
printf("6");
mma_send_byte(0);
printf("7");
mma_restart(0x4c, 0);
for (int i = 0; i <= 0xa; i++) {
int data;
if (i == 0xa) {
data = mma_read_nack();
} else {
data = mma_read_ack();
}
printf(" %02x", data);
}
printf("\n");
mma_start(0x4c, 1);
mma_send_byte(7); // mode
mma_send_byte(1); // active mode
mma_stop();
for (;;) {
sys_tick_delay_ms(500);
mma_start(0x4c, 1);
mma_send_byte(0);
mma_restart(0x4c, 0);
for (int i = 0; i <= 3; i++) {
int data;
if (i == 3) {
data = mma_read_nack();
printf(" %02x\n", data);
} else {
data = mma_read_ack() & 0x3f;
if (data & 0x20) {
data |= 0xc0;
}
printf(" % 2d", data);
}
}
}
}
// SD card testing // SD card testing
if (0) { if (0) {
//sdio_init(); //sdio_init();
......
...@@ -4,22 +4,39 @@ ...@@ -4,22 +4,39 @@
#include <stm32f4xx_rcc.h> #include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h> #include <stm32f4xx_gpio.h>
#include "misc.h"
#include "systick.h"
#include "mma.h" #include "mma.h"
void mma_init(void) { void mma_init(void) {
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1
//gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); //gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
//gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); //gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
//gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */); //gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */);
//gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */); //gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */);
// XXX untested GPIO init! (was above code) // XXX untested GPIO init! (was above code)
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
// PB5 is connected to AVDD; pull high to enable MMA device
GPIOB->BSRRH = GPIO_Pin_5; // PB5 low to start with
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// PB6=SCL, PB7=SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure);
// alternate functions for SCL and SDA
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
...@@ -43,6 +60,11 @@ void mma_init(void) { ...@@ -43,6 +60,11 @@ void mma_init(void) {
// enable the I2C peripheral // enable the I2C peripheral
I2C1->CR1 |= I2C_CR1_PE; I2C1->CR1 |= I2C_CR1_PE;
// wait 20ms, then turn on AVDD, then wait 20ms again; this seems to work, but maybe can decrease delays
sys_tick_delay_ms(20);
GPIOB->BSRRL = GPIO_Pin_5;
sys_tick_delay_ms(20);
// set START bit in CR1 to generate a start cond! // set START bit in CR1 to generate a start cond!
} }
...@@ -58,27 +80,47 @@ void mma_restart(uint8_t addr, int write) { ...@@ -58,27 +80,47 @@ void mma_restart(uint8_t addr, int write) {
I2C1->CR1 |= I2C_CR1_START; I2C1->CR1 |= I2C_CR1_START;
// wait for BUSY, MSL and SB --> Slave has acknowledged start condition // wait for BUSY, MSL and SB --> Slave has acknowledged start condition
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00030001) != 0x00030001) { while ((i2c_get_sr() & 0x00030001) != 0x00030001) {
if (--timeout == 0) {
printf("timeout in mma_restart\n");
return;
}
} }
if (write) { if (write) {
// send address and write bit // send address and write bit
I2C1->DR = (addr << 1) | 0; I2C1->DR = (addr << 1) | 0;
// wait for BUSY, MSL, ADDR, TXE and TRA // wait for BUSY, MSL, ADDR, TXE and TRA
timeout = 1000000;
while ((i2c_get_sr() & 0x00070082) != 0x00070082) { while ((i2c_get_sr() & 0x00070082) != 0x00070082) {
if (--timeout == 0) {
printf("timeout in mma_restart write\n");
return;
}
} }
} else { } else {
// send address and read bit // send address and read bit
I2C1->DR = (addr << 1) | 1; I2C1->DR = (addr << 1) | 1;
// wait for BUSY, MSL and ADDR flags // wait for BUSY, MSL and ADDR flags
timeout = 1000000;
while ((i2c_get_sr() & 0x00030002) != 0x00030002) { while ((i2c_get_sr() & 0x00030002) != 0x00030002) {
if (--timeout == 0) {
printf("timeout in mma_restart read\n");
return;
}
} }
} }
} }
void mma_start(uint8_t addr, int write) { void mma_start(uint8_t addr, int write) {
// wait until I2C is not busy // wait until I2C is not busy
uint32_t timeout = 1000000;
while (I2C1->SR2 & I2C_SR2_BUSY) { while (I2C1->SR2 & I2C_SR2_BUSY) {
if (--timeout == 0) {
printf("timeout in mma_start\n");
return;
}
} }
// do rest of start // do rest of start
...@@ -89,11 +131,11 @@ void mma_send_byte(uint8_t data) { ...@@ -89,11 +131,11 @@ void mma_send_byte(uint8_t data) {
// send byte // send byte
I2C1->DR = data; I2C1->DR = data;
// wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted) // wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted)
int timeout = 1000000; uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00070084) != 0x00070084) { while ((i2c_get_sr() & 0x00070084) != 0x00070084) {
if (timeout-- <= 0) { if (--timeout == 0) {
printf("mma_send_byte timed out!\n"); printf("timeout in mma_send_byte\n");
break; return;
} }
} }
} }
...@@ -102,7 +144,12 @@ uint8_t mma_read_ack(void) { ...@@ -102,7 +144,12 @@ uint8_t mma_read_ack(void) {
// enable ACK of received byte // enable ACK of received byte
I2C1->CR1 |= I2C_CR1_ACK; I2C1->CR1 |= I2C_CR1_ACK;
// wait for BUSY, MSL and RXNE (byte received) // wait for BUSY, MSL and RXNE (byte received)
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00030040) != 0x00030040) { while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
if (--timeout == 0) {
printf("timeout in mma_read_ack\n");
break;
}
} }
// read and return data // read and return data
uint8_t data = I2C1->DR; uint8_t data = I2C1->DR;
...@@ -115,7 +162,12 @@ uint8_t mma_read_nack(void) { ...@@ -115,7 +162,12 @@ uint8_t mma_read_nack(void) {
// last byte should apparently also generate a stop condition // last byte should apparently also generate a stop condition
I2C1->CR1 |= I2C_CR1_STOP; I2C1->CR1 |= I2C_CR1_STOP;
// wait for BUSY, MSL and RXNE (byte received) // wait for BUSY, MSL and RXNE (byte received)
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00030040) != 0x00030040) { while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
if (--timeout == 0) {
printf("timeout in mma_read_nack\n");
break;
}
} }
// read and return data // read and return data
uint8_t data = I2C1->DR; uint8_t data = I2C1->DR;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment