accel.c 4.34 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <stdio.h>
#include <string.h>

#include <stm32f4xx_hal.h>

#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "accel.h"

#define MMA_ADDR (0x98)
#define MMA_REG_MODE (7)

STATIC I2C_HandleTypeDef I2cHandle;

void accel_init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;

    // PB5 is connected to AVDD; pull high to enable MMA accel device
    GPIOB->BSRRH = GPIO_PIN_5; // turn off AVDD
    GPIO_InitStructure.Pin = GPIO_PIN_5;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

    // wait 20ms, then turn on AVDD, then wait 20ms again
    HAL_Delay(20);
    GPIOB->BSRRL = GPIO_PIN_5;
    HAL_Delay(20);

    // PB6=SCL, PB7=SDA
    GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
    GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines
    GPIO_InitStructure.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

    // enable the I2C1 clock
    __I2C1_CLK_ENABLE();

    // set up the I2C1 device
    memset(&I2cHandle, 0, sizeof(I2C_HandleTypeDef));
    I2cHandle.Instance = I2C1;
    I2cHandle.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
    I2cHandle.Init.ClockSpeed      = 400000;
    I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
    I2cHandle.Init.DutyCycle       = I2C_DUTYCYCLE_16_9;
    I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
    I2cHandle.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLED;
    I2cHandle.Init.OwnAddress1     = 0xfe; // unused
    I2cHandle.Init.OwnAddress2     = 0xfe; // unused

    if (HAL_I2C_Init(&I2cHandle) != HAL_OK) {
        // init error
        printf("accel_init: HAL_I2C_Init failed\n");
        return;
    }

    HAL_StatusTypeDef status;

    //printf("IsDeviceReady\n");
    for (int i = 0; i < 10; i++) {
        status = HAL_I2C_IsDeviceReady(&I2cHandle, MMA_ADDR, 10, 200);
        //printf("  got %d\n", status);
        if (status == HAL_OK) {
            break;
        }
    }

    //printf("MemWrite\n");
    uint8_t data[1];
    data[0] = 1; // active mode
    status = HAL_I2C_Mem_Write(&I2cHandle, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
    //printf("  got %d\n", status);
}

/******************************************************************************/
/* Micro Python bindings                                                      */

int accel_buf[12];

mp_obj_t pyb_accel_read(void) {
    for (int i = 0; i <= 6; i += 3) {
        accel_buf[0 + i] = accel_buf[0 + i + 3];
        accel_buf[1 + i] = accel_buf[1 + i + 3];
        accel_buf[2 + i] = accel_buf[2 + i + 3];
    }

    uint8_t data_[4];
    HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, 0, I2C_MEMADD_SIZE_8BIT, data_, 4, 200);
    accel_buf[9] = data_[0] & 0x3f; if (accel_buf[9] & 0x20) accel_buf[9] |= ~0x1f;
    accel_buf[10] = data_[1] & 0x3f; if (accel_buf[10] & 0x20) accel_buf[10] |= ~0x1f;
    accel_buf[11] = data_[2] & 0x3f; if (accel_buf[11] & 0x20) accel_buf[11] |= ~0x1f;
    int jolt_info = data_[3];

    mp_obj_t data[4];
    data[0] = mp_obj_new_int(accel_buf[0] + accel_buf[3] + accel_buf[6] + accel_buf[9]);
    data[1] = mp_obj_new_int(accel_buf[1] + accel_buf[4] + accel_buf[7] + accel_buf[10]);
    data[2] = mp_obj_new_int(accel_buf[2] + accel_buf[5] + accel_buf[8] + accel_buf[11]);
    data[3] = mp_obj_new_int(jolt_info);

    return rt_build_tuple(4, data);
}

MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_obj, pyb_accel_read);

/*
mp_obj_t pyb_accel_read_all(void) {
    mp_obj_t data[11];
    accel_start(MMA_ADDR, 1);
    accel_send_byte(0);
    accel_restart(MMA_ADDR, 0);
    for (int i = 0; i <= 9; i++) {
        data[i] = mp_obj_new_int(accel_read_ack());
    }
    data[10] = mp_obj_new_int(accel_read_nack());

    return rt_build_tuple(11, data);
}

MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_all_obj, pyb_accel_read_all);

mp_obj_t pyb_accel_write_mode(mp_obj_t o_int, mp_obj_t o_mode) {
    accel_start(MMA_ADDR, 1);
    accel_send_byte(6); // start at int
    accel_send_byte(mp_obj_get_int(o_int));
    accel_send_byte(mp_obj_get_int(o_mode));
    accel_stop();
    return mp_const_none;
}

MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_write_mode_obj, pyb_accel_write_mode);
*/