Skip to content

Commit 5052177

Browse files
committed
Setup files for busio
1 parent 5dd6010 commit 5052177

File tree

8 files changed

+637
-0
lines changed

8 files changed

+637
-0
lines changed

ports/analog/common-hal/busio/I2C.c

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/*
2+
* This file is part of Adafruit for EFR32 project
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
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 "shared-bindings/busio/I2C.h"
28+
#include "py/mperrno.h"
29+
#include "py/runtime.h"
30+
#include "shared-bindings/microcontroller/__init__.h"
31+
#include "shared-bindings/microcontroller/Pin.h"
32+
33+
static I2CSPM_Init_TypeDef i2cspm_init;
34+
static bool in_used = false;
35+
36+
// Construct I2C protocol, this function init i2c peripheral
37+
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
38+
const mcu_pin_obj_t *scl,
39+
const mcu_pin_obj_t *sda,
40+
uint32_t frequency, uint32_t timeout) {
41+
42+
// Ensure the object starts in its deinit state.
43+
common_hal_busio_i2c_mark_deinit(self);
44+
45+
if ((scl != NULL) && (sda != NULL)) {
46+
if (scl->function_list[ DEFAULT_I2C_PERIPHERAL == I2C1?
47+
FN_I2C1_SCL : FN_I2C0_SCL] == 1 &&
48+
scl->function_list[DEFAULT_I2C_PERIPHERAL == I2C1?
49+
FN_I2C1_SDA : FN_I2C0_SDA] == 1) {
50+
self->scl = scl;
51+
self->sda = sda;
52+
self->has_lock = false;
53+
i2cspm_init.sclPort = self->scl->port;
54+
i2cspm_init.sclPin = self->scl->number;
55+
i2cspm_init.sdaPort = self->sda->port;
56+
i2cspm_init.sdaPin = self->sda->number;
57+
i2cspm_init.port = DEFAULT_I2C_PERIPHERAL;
58+
i2cspm_init.i2cRefFreq = 0;
59+
i2cspm_init.i2cMaxFreq = I2C_FREQ_STANDARD_MAX;
60+
i2cspm_init.i2cClhr = i2cClockHLRStandard;
61+
62+
self->i2cspm = i2cspm_init.port;
63+
I2CSPM_Init(&i2cspm_init);
64+
common_hal_mcu_pin_claim(scl);
65+
common_hal_mcu_pin_claim(sda);
66+
in_used = true;
67+
} else {
68+
mp_raise_ValueError(MP_ERROR_TEXT("Hardware in use, try alternative pins"));
69+
}
70+
} else {
71+
raise_ValueError_invalid_pins();
72+
}
73+
}
74+
75+
// Never reset I2C obj when reload
76+
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
77+
common_hal_never_reset_pin(self->sda);
78+
common_hal_never_reset_pin(self->scl);
79+
}
80+
81+
// Check I2C status, deinited or not
82+
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
83+
return self->sda == NULL;
84+
}
85+
86+
// Deinit i2c obj, reset I2C pin
87+
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
88+
if (common_hal_busio_i2c_deinited(self)) {
89+
return;
90+
}
91+
I2C_Reset(self->i2cspm);
92+
common_hal_reset_pin(self->sda);
93+
common_hal_reset_pin(self->scl);
94+
self->i2cspm = NULL;
95+
in_used = false;
96+
common_hal_busio_i2c_mark_deinit(self);
97+
}
98+
99+
void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) {
100+
self->sda = NULL;
101+
}
102+
103+
// Probe device in I2C bus
104+
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
105+
I2C_TransferSeq_TypeDef seq;
106+
I2C_TransferReturn_TypeDef ret;
107+
uint8_t data = 0;
108+
109+
seq.addr = addr << 1;
110+
seq.flags = I2C_FLAG_READ;
111+
112+
seq.buf[0].data = &data;
113+
seq.buf[0].len = 1;
114+
115+
ret = I2CSPM_Transfer(self->i2cspm, &seq);
116+
if (ret != i2cTransferDone) {
117+
return false;
118+
}
119+
return true;
120+
}
121+
122+
// Lock I2C bus
123+
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
124+
if (common_hal_busio_i2c_deinited(self)) {
125+
return false;
126+
}
127+
bool grabbed_lock = false;
128+
129+
if (!self->has_lock) {
130+
grabbed_lock = true;
131+
self->has_lock = true;
132+
}
133+
134+
return grabbed_lock;
135+
}
136+
137+
// Check I2C lock status
138+
bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
139+
return self->has_lock;
140+
}
141+
142+
// Unlock I2C bus
143+
void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
144+
self->has_lock = false;
145+
}
146+
147+
// Write data to the device selected by address
148+
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
149+
const uint8_t *data, size_t len) {
150+
151+
I2C_TransferSeq_TypeDef seq;
152+
I2C_TransferReturn_TypeDef ret;
153+
154+
seq.addr = addr << 1;
155+
seq.flags = I2C_FLAG_WRITE;
156+
157+
seq.buf[0].data = (uint8_t *)data;
158+
seq.buf[0].len = len;
159+
160+
ret = I2CSPM_Transfer(self->i2cspm, &seq);
161+
if (ret != i2cTransferDone) {
162+
return MP_EIO;
163+
}
164+
return 0;
165+
}
166+
167+
// Read into buffer from the device selected by address
168+
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self,
169+
uint16_t addr,
170+
uint8_t *data, size_t len) {
171+
172+
I2C_TransferSeq_TypeDef seq;
173+
I2C_TransferReturn_TypeDef ret;
174+
175+
seq.addr = addr << 1;
176+
seq.flags = I2C_FLAG_READ;
177+
178+
seq.buf[0].data = data;
179+
seq.buf[0].len = len;
180+
181+
ret = I2CSPM_Transfer(self->i2cspm, &seq);
182+
if (ret != i2cTransferDone) {
183+
return MP_EIO;
184+
}
185+
return 0;
186+
}
187+
188+
// Write the bytes from out_data to the device selected by address,
189+
uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr,
190+
uint8_t *out_data, size_t out_len,
191+
uint8_t *in_data, size_t in_len) {
192+
193+
I2C_TransferSeq_TypeDef seq;
194+
I2C_TransferReturn_TypeDef ret;
195+
196+
seq.addr = addr << 1;
197+
seq.flags = I2C_FLAG_WRITE_READ;
198+
// Select command to issue
199+
seq.buf[0].data = out_data;
200+
seq.buf[0].len = out_len;
201+
// Select location/length of data to be read
202+
seq.buf[1].data = in_data;
203+
seq.buf[1].len = in_len;
204+
205+
ret = I2CSPM_Transfer(self->i2cspm, &seq);
206+
if (ret != i2cTransferDone) {
207+
return MP_EIO;
208+
}
209+
return 0;
210+
}

ports/analog/common-hal/busio/I2C.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#pragma once
8+
9+
#include "common-hal/microcontroller/Pin.h"
10+
// FIXME: Silabs includes "peripherals/periph.h. Figure out what's in this file. "
11+
#include "py/obj.h"
12+
13+
// HAL-specific
14+
#include "i2c.h"
15+
#include "gpio.h"
16+
17+
// Define a struct for what BUSIO.I2C should carry
18+
typedef struct {
19+
mp_obj_base_t base;
20+
mxc_i2c_regs_t* i2c_regs;
21+
bool has_lock;
22+
const mcu_pin_obj_t *scl;
23+
const mcu_pin_obj_t *sda;
24+
} busio_i2c_obj_t;

0 commit comments

Comments
 (0)