Skip to content

Commit 3fbddfd

Browse files
authored
Merge pull request #6758 from gamblor21/rp2040_i2ctarget
Rp2040 i2ctarget support
2 parents 7717ab8 + 7584363 commit 3fbddfd

File tree

4 files changed

+204
-1
lines changed

4 files changed

+204
-1
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Mark Komus, Ken Stillson, im-redactd
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/i2ctarget/I2CTarget.h"
28+
29+
#include "common-hal/busio/I2C.h"
30+
31+
#include "py/mperrno.h"
32+
#include "py/mphal.h"
33+
#include "shared-bindings/busio/I2C.h"
34+
#include "shared-bindings/microcontroller/Pin.h"
35+
#include "py/runtime.h"
36+
37+
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
38+
39+
STATIC i2c_inst_t *i2c[2] = {i2c0, i2c1};
40+
41+
#define NO_PIN 0xff
42+
43+
void common_hal_i2ctarget_i2c_target_construct(i2ctarget_i2c_target_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda,
44+
uint8_t *addresses, unsigned int num_addresses, bool smbus) {
45+
self->peripheral = NULL;
46+
47+
// I2C pins have a regular pattern. SCL is always odd and SDA is even. They match up in pairs
48+
// so we can divide by two to get the instance. This pattern repeats.
49+
size_t scl_instance = (scl->number / 2) % 2;
50+
size_t sda_instance = (sda->number / 2) % 2;
51+
if (scl->number % 2 == 1 && sda->number % 2 == 0 && scl_instance == sda_instance) {
52+
self->peripheral = i2c[sda_instance];
53+
}
54+
55+
if (self->peripheral == NULL) {
56+
raise_ValueError_invalid_pins();
57+
}
58+
59+
if ((i2c_get_hw(self->peripheral)->enable & I2C_IC_ENABLE_ENABLE_BITS) != 0) {
60+
mp_raise_ValueError(translate("I2C peripheral in use"));
61+
}
62+
63+
if (num_addresses > 1) {
64+
mp_raise_ValueError(translate("Only one address is allowed"));
65+
}
66+
67+
self->addresses = addresses;
68+
self->num_addresses = num_addresses;
69+
self->scl_pin = scl->number;
70+
self->sda_pin = sda->number;
71+
72+
// Have to specify a baudrate even if the i2c target does not use it
73+
const uint32_t frequency = 400000;
74+
i2c_init(self->peripheral, frequency);
75+
76+
gpio_set_function(sda->number, GPIO_FUNC_I2C);
77+
gpio_set_function(scl->number, GPIO_FUNC_I2C);
78+
79+
gpio_set_pulls(sda->number, true, false);
80+
gpio_set_pulls(scl->number, true, false);
81+
82+
self->peripheral->hw->intr_mask |= I2C_IC_INTR_MASK_M_RESTART_DET_BITS;
83+
i2c_set_slave_mode(self->peripheral, true, self->addresses[0]);
84+
85+
return;
86+
}
87+
88+
bool common_hal_i2ctarget_i2c_target_deinited(i2ctarget_i2c_target_obj_t *self) {
89+
return self->sda_pin == NO_PIN;
90+
}
91+
92+
void common_hal_i2ctarget_i2c_target_deinit(i2ctarget_i2c_target_obj_t *self) {
93+
if (common_hal_i2ctarget_i2c_target_deinited(self)) {
94+
return;
95+
}
96+
97+
i2c_deinit(self->peripheral);
98+
99+
reset_pin_number(self->sda_pin);
100+
reset_pin_number(self->scl_pin);
101+
self->sda_pin = NO_PIN;
102+
self->scl_pin = NO_PIN;
103+
104+
return;
105+
}
106+
107+
static int i2c_peripheral_check_error(i2ctarget_i2c_target_obj_t *self, bool raise) {
108+
return 0;
109+
}
110+
111+
int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *self, uint8_t *address, bool *is_read, bool *is_restart) {
112+
if (!((self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS) || (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RD_REQ_BITS))) {
113+
return 0;
114+
}
115+
116+
*address = self->peripheral->hw->sar;
117+
*is_read = !(self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS);
118+
*is_restart = ((self->peripheral->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_RD_REQ_RESET) != 0);
119+
120+
common_hal_i2ctarget_i2c_target_ack(self, true);
121+
return 1;
122+
}
123+
124+
int common_hal_i2ctarget_i2c_target_read_byte(i2ctarget_i2c_target_obj_t *self, uint8_t *data) {
125+
if (self->peripheral->hw->status & I2C_IC_STATUS_RFNE_BITS) {
126+
*data = (uint8_t)self->peripheral->hw->data_cmd;
127+
return 1;
128+
} else {
129+
return 0;
130+
}
131+
}
132+
133+
int common_hal_i2ctarget_i2c_target_write_byte(i2ctarget_i2c_target_obj_t *self, uint8_t data) {
134+
if (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_TX_ABRT_BITS) {
135+
self->peripheral->hw->clr_tx_abrt;
136+
}
137+
138+
const size_t IC_TX_BUFFER_DEPTH = 16;
139+
size_t space = IC_TX_BUFFER_DEPTH - self->peripheral->hw->txflr;
140+
141+
if (space > 0) {
142+
self->peripheral->hw->data_cmd = data;
143+
self->peripheral->hw->clr_rd_req;
144+
return 1;
145+
} else {
146+
return 0;
147+
}
148+
}
149+
150+
void common_hal_i2ctarget_i2c_target_ack(i2ctarget_i2c_target_obj_t *self, bool ack) {
151+
return;
152+
}
153+
154+
void common_hal_i2ctarget_i2c_target_close(i2ctarget_i2c_target_obj_t *self) {
155+
return;
156+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Mark Komus, Ken Stillson, im-redactd
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_RPI_COMMON_HAL_I2C_TARGET_H
28+
#define MICROPY_INCLUDED_RPI_COMMON_HAL_I2C_TARGET_H
29+
30+
#include "py/obj.h"
31+
#include "common-hal/microcontroller/Pin.h"
32+
#include "src/rp2_common/hardware_i2c/include/hardware/i2c.h"
33+
34+
typedef struct {
35+
mp_obj_base_t base;
36+
37+
uint8_t *addresses;
38+
unsigned int num_addresses;
39+
40+
i2c_inst_t *peripheral;
41+
42+
uint8_t scl_pin;
43+
uint8_t sda_pin;
44+
} i2ctarget_i2c_target_obj_t;
45+
46+
#endif MICROPY_INCLUDED_RPI_COMMON_HAL_BUSIO_I2C_TARGET_H
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// No i2ctarget module functions.

ports/raspberrypi/mpconfigport.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ CIRCUITPY_ROTARYIO_SOFTENCODER = 1
2020
# Things that need to be implemented.
2121
# Use PWM interally
2222
CIRCUITPY_FREQUENCYIO = 0
23-
CIRCUITPY_I2CTARGET = 0
23+
CIRCUITPY_I2CTARGET = 1
2424
CIRCUITPY_NVM = 1
2525
# Use PIO interally
2626
CIRCUITPY_PULSEIO ?= 1

0 commit comments

Comments
 (0)