Skip to content
This repository was archived by the owner on Sep 6, 2023. It is now read-only.

Commit 192a032

Browse files
committed
esp32/machine_hspi.c: Adding HW SPI support
esp32/machine_hspi.h: Adding HW SPI support
1 parent f41a01a commit 192a032

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed

esp32/machine_hspi.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdio.h>
28+
#include <stdint.h>
29+
#include <string.h>
30+
31+
32+
#include "py/runtime.h"
33+
#include "py/stream.h"
34+
#include "py/mphal.h"
35+
#include "extmod/machine_spi.h"
36+
#include "machine_hspi.h"
37+
#include "modmachine.h"
38+
#include "hspi.h"
39+
40+
// if a port didn't define MSB/LSB constants then provide them
41+
#ifndef MICROPY_PY_MACHINE_SPI_MSB
42+
#define MICROPY_PY_MACHINE_SPI_MSB (0)
43+
#define MICROPY_PY_MACHINE_SPI_LSB (1)
44+
#endif
45+
46+
47+
48+
STATIC void machine_hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
49+
machine_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
50+
int bits_to_send = len * self->bits;
51+
if (self->deinitialized) {
52+
return;
53+
}
54+
55+
struct spi_transaction_t transaction = {
56+
.flags = 0,
57+
.length = bits_to_send,
58+
.tx_buffer = src,
59+
.rx_buffer = dest,
60+
};
61+
bool shortMsg = len <= 4;
62+
63+
if(shortMsg) {
64+
if (src != NULL) {
65+
memcpy(&transaction.tx_data, src, len);
66+
transaction.flags |= SPI_TRANS_USE_TXDATA;
67+
}
68+
if (dest != NULL) {
69+
transaction.flags |= SPI_TRANS_USE_RXDATA;
70+
}
71+
}
72+
73+
spi_device_transmit(self->spi, &transaction);
74+
75+
if (shortMsg && dest != NULL) {
76+
memcpy(dest, &transaction.rx_data, len);
77+
}
78+
}
79+
80+
/******************************************************************************/
81+
// MicroPython bindings for HSPI
82+
83+
STATIC void machine_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
84+
machine_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
85+
mp_printf(print, "HSPI(id=%u, baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, sck=%d, mosi=%d, miso=%d)",
86+
self->host, self->baudrate, self->polarity,
87+
self->phase, self->bits, self->firstbit,
88+
self->sck, self->mosi, self->miso );
89+
}
90+
91+
STATIC void machine_hspi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
92+
machine_hspi_obj_t *self = (machine_hspi_obj_t*)self_in;
93+
esp_err_t ret;
94+
95+
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
96+
static const mp_arg_t allowed_args[] = {
97+
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 1} },
98+
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
99+
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
100+
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
101+
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
102+
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} },
103+
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
104+
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
105+
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
106+
};
107+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
108+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
109+
allowed_args, args);
110+
111+
self->host = args[ARG_id].u_int;
112+
self->baudrate = args[ARG_baudrate].u_int;
113+
self->polarity = args[ARG_polarity].u_int ? 1 : 0;
114+
self->phase = args[ARG_phase].u_int ? 1 : 0;
115+
self->bits = args[ARG_bits].u_int;
116+
self->firstbit = args[ARG_firstbit].u_int;
117+
self->sck = args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj);
118+
self->miso = args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj);
119+
self->mosi = args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj);
120+
self->deinitialized = false;
121+
122+
spi_bus_config_t buscfg = {
123+
.miso_io_num = self->miso,
124+
.mosi_io_num = self->mosi,
125+
.sclk_io_num = self->sck,
126+
.quadwp_io_num = -1,
127+
.quadhd_io_num = -1
128+
};
129+
spi_device_interface_config_t devcfg = {
130+
.clock_speed_hz = self->baudrate,
131+
.mode = self->phase | (self->polarity << 1),
132+
.spics_io_num = -1, // No CS pin
133+
.queue_size = 1,
134+
.pre_cb = NULL
135+
};
136+
137+
//Initialize the SPI bus
138+
// FIXME: Does the DMA matter? There are two
139+
ret=spi_bus_initialize(self->host, &buscfg, 1);
140+
assert(ret == ESP_OK);
141+
ret=spi_bus_add_device(self->host, &devcfg, &self->spi);
142+
assert(ret == ESP_OK);
143+
}
144+
145+
STATIC void machine_hspi_deinit(mp_obj_base_t *self_in) {
146+
machine_hspi_obj_t *self = (machine_hspi_obj_t*)self_in;
147+
esp_err_t ret;
148+
if (!self->deinitialized) {
149+
self->deinitialized = true;
150+
ret = spi_bus_remove_device(self->spi);
151+
assert(ret == ESP_OK);
152+
ret = spi_bus_free(self->host);
153+
assert(ret == ESP_OK);
154+
}
155+
}
156+
157+
mp_obj_t machine_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
158+
// args[0] holds the id of the peripheral
159+
int host = mp_obj_get_int(args[0]);
160+
if (host != HSPI_HOST && host != VSPI_HOST) {
161+
mp_raise_ValueError("SPI ID must be either HSPI(1) or VSPI(2)");
162+
}
163+
164+
machine_hspi_obj_t *self = m_new_obj(machine_hspi_obj_t);
165+
self->base.type = &machine_hspi_type;
166+
// set defaults
167+
mp_map_t kw_args;
168+
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
169+
machine_hspi_init((mp_obj_base_t*)self, n_args, args, &kw_args);
170+
return MP_OBJ_FROM_PTR(self);
171+
}
172+
173+
STATIC const mp_machine_spi_p_t machine_hspi_p = {
174+
.init = machine_hspi_init,
175+
.deinit = machine_hspi_deinit,
176+
.transfer = machine_hspi_transfer,
177+
};
178+
179+
const mp_obj_type_t machine_hspi_type = {
180+
{ &mp_type_type },
181+
.name = MP_QSTR_HSPI,
182+
.print = machine_hspi_print,
183+
.make_new = machine_hspi_make_new,
184+
.protocol = &machine_hspi_p,
185+
.locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict,
186+
};

esp32/machine_hspi.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_MACHINE_HSPI_H
28+
#define MICROPY_INCLUDED_MACHINE_HSPI_H
29+
30+
#include "driver/spi_master.h"
31+
32+
typedef struct _machine_hspi_obj_t {
33+
mp_obj_base_t base;
34+
spi_host_device_t host;
35+
uint32_t baudrate;
36+
uint8_t polarity;
37+
uint8_t phase;
38+
uint8_t bits;
39+
uint8_t firstbit;
40+
int8_t sck;
41+
int8_t mosi;
42+
int8_t miso;
43+
spi_device_handle_t spi;
44+
bool deinitialized;
45+
} machine_hspi_obj_t;
46+
47+
extern const mp_obj_type_t machine_hspi_type ;
48+
49+
#endif // MICROPY_INCLUDED_MACHINE_HSPI_H

0 commit comments

Comments
 (0)