diff --git a/py/runtime.c b/py/runtime.c
index 9da5688763809408c6bb762a4511f4f3392ea1e4..a1bd676367d86482768d5fbe4afc86c854dcfc57 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -319,6 +319,10 @@ static bool fit_small_int(py_small_int_t o) {
     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_base_t *o = m_new(py_obj_base_t, 1);
     o->kind = O_CONST;
diff --git a/py/runtime.h b/py/runtime.h
index 326ca0833bb6f2a68774066fec0020a4682710d9..98d77c8e727172f6ea268db50d53c612981a7417 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -99,6 +99,7 @@ void py_obj_print(py_obj_t o);
 int rt_is_true(py_obj_t arg);
 int py_get_int(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_name(qstr qstr);
 py_obj_t rt_load_global(qstr qstr);
diff --git a/stm/main.c b/stm/main.c
index 94c40f27e983145a64ec408719be1012235d9c4f..801a0decd29bb06b557244a9f06ada73c1581e10 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -433,6 +433,24 @@ py_obj_t pyb_servo_set(py_obj_t value) {
     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) {
     // TODO disable JTAG
 
@@ -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("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("mma"), rt_make_function_0(pyb_mma_read));
         rt_store_name(qstr_from_str_static("pyb"), m);
     }
 
@@ -554,6 +573,62 @@ soft_reset:
     // USB
     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
     led_state(PYB_LED_G1, 0);
 
@@ -737,60 +812,6 @@ soft_reset:
         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
     if (0) {
         //sdio_init();
diff --git a/stm/mma.c b/stm/mma.c
index 02f6d38c414e2b3960f48ac0d86dc573712f2bf6..48817b2d9786d1b978ed5fa82dc36976b505ca6f 100644
--- a/stm/mma.c
+++ b/stm/mma.c
@@ -4,22 +4,39 @@
 #include <stm32f4xx_rcc.h>
 #include <stm32f4xx_gpio.h>
 
+#include "misc.h"
+#include "systick.h"
 #include "mma.h"
 
 void mma_init(void) {
     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, 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, 7, 4 /* AF 4 for I2C1 */);
     // XXX untested GPIO init! (was above code)
+
     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_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
     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);
+
+    // alternate functions for SCL and SDA
     GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
     GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
 
@@ -43,6 +60,11 @@ void mma_init(void) {
     // enable the I2C peripheral
     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!
 }
 
@@ -58,27 +80,47 @@ void mma_restart(uint8_t addr, int write) {
     I2C1->CR1 |= I2C_CR1_START;
 
     // wait for BUSY, MSL and SB --> Slave has acknowledged start condition
+    uint32_t timeout = 1000000;
     while ((i2c_get_sr() & 0x00030001) != 0x00030001) {
+        if (--timeout == 0) {
+            printf("timeout in mma_restart\n");
+            return;
+        }
     }
 
     if (write) {
         // send address and write bit
         I2C1->DR = (addr << 1) | 0;
         // wait for BUSY, MSL, ADDR, TXE and TRA
+        timeout = 1000000;
         while ((i2c_get_sr() & 0x00070082) != 0x00070082) {
+            if (--timeout == 0) {
+                printf("timeout in mma_restart write\n");
+                return;
+            }
         }
     } else {
         // send address and read bit
         I2C1->DR = (addr << 1) | 1;
         // wait for BUSY, MSL and ADDR flags
+        timeout = 1000000;
         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) {
     // wait until I2C is not busy
+    uint32_t timeout = 1000000;
     while (I2C1->SR2 & I2C_SR2_BUSY) {
+        if (--timeout == 0) {
+            printf("timeout in mma_start\n");
+            return;
+        }
     }
 
     // do rest of start
@@ -89,11 +131,11 @@ void mma_send_byte(uint8_t data) {
     // send byte
     I2C1->DR = data;
     // wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted)
-    int timeout = 1000000;
+    uint32_t timeout = 1000000;
     while ((i2c_get_sr() & 0x00070084) != 0x00070084) {
-        if (timeout-- <= 0) {
-            printf("mma_send_byte timed out!\n");
-            break;
+        if (--timeout == 0) {
+            printf("timeout in mma_send_byte\n");
+            return;
         }
     }
 }
@@ -102,7 +144,12 @@ uint8_t mma_read_ack(void) {
     // enable ACK of received byte
     I2C1->CR1 |= I2C_CR1_ACK;
     // wait for BUSY, MSL and RXNE (byte received)
+    uint32_t timeout = 1000000;
     while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
+        if (--timeout == 0) {
+            printf("timeout in mma_read_ack\n");
+            break;
+        }
     }
     // read and return data
     uint8_t data = I2C1->DR;
@@ -115,7 +162,12 @@ uint8_t mma_read_nack(void) {
     // last byte should apparently also generate a stop condition
     I2C1->CR1 |= I2C_CR1_STOP;
     // wait for BUSY, MSL and RXNE (byte received)
+    uint32_t timeout = 1000000;
     while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
+        if (--timeout == 0) {
+            printf("timeout in mma_read_nack\n");
+            break;
+        }
     }
     // read and return data
     uint8_t data = I2C1->DR;