Commit 2dd47239 authored by Daniel Campora's avatar Daniel Campora
Browse files

cc3200: Make API more similar to stmhal.

In general the changes are:

1. Peripheral (UART, SPI, ADC, I2C, Timer) IDs start from 1, not zero.
2. Make I2C and SPI require the ID even when there's only one bus.
3. Make I2C and SPI accept 'mode' parameter even though only MASTER
   is supported.
parent 65453362
......@@ -34,7 +34,7 @@
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART 1
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
......
......@@ -34,10 +34,6 @@
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3
#define MICROPY_SYS_LED_PORT GPIOA3_BASE
......
......@@ -34,10 +34,6 @@
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3
#define MICROPY_SYS_LED_PORT GPIOA3_BASE
......
......@@ -57,7 +57,7 @@
///
/// Usage:
///
/// adc = pyb.ADC(channel) # create an adc object on the given channel (0 to 3)
/// adc = pyb.ADC(channel) # create an adc object on the given channel (1 to 4)
/// this automatically configures the pin associated to
/// that analog channel.
/// adc.read() # read channel value
......@@ -76,7 +76,7 @@
typedef struct {
mp_obj_base_t base;
byte channel;
byte num;
byte idx;
} pyb_adc_obj_t;
/******************************************************************************
......@@ -102,7 +102,7 @@ STATIC pyb_adc_obj_t pyb_adc_obj[PYB_ADC_NUM_CHANNELS];
STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_adc_obj_t *self = self_in;
mp_printf(print, "<ADC, channel=%u>", self->num);
mp_printf(print, "<ADC, channel=%u>", (self->idx + 1));
}
/// \classmethod \constructor(channel)
......@@ -113,10 +113,10 @@ STATIC mp_obj_t adc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// the first argument is the channel number
uint num = mp_obj_get_int(args[0]);
int32_t idx = mp_obj_get_int(args[0]) - 1;
const pin_obj_t *pin;
uint channel;
switch (num) {
switch (idx) {
case 0:
channel = ADC_CH_0;
pin = &pin_GPIO2;
......@@ -139,10 +139,10 @@ STATIC mp_obj_t adc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
}
// disable the callback before re-configuring
pyb_adc_obj_t *self = &pyb_adc_obj[num];
pyb_adc_obj_t *self = &pyb_adc_obj[idx];
self->base.type = &pyb_adc_type;
self->channel = channel;
self->num = num;
self->idx = idx;
// configure the pin in analog mode
pin_config ((pin_obj_t *)pin, PIN_MODE_0, GPIO_DIR_MODE_IN, PYBPIN_ANALOG_TYPE, PIN_STRENGTH_2MA);
......
......@@ -56,10 +56,10 @@
///
/// from pyb import I2C
///
/// i2c = I2C() # create
/// i2c = I2C(50000) # create and init with a 50KHz baudrate
/// i2c.init(100000) # init with a 100KHz baudrate
/// i2c.deinit() # turn off the peripheral
/// i2c = I2C(1) # create
/// i2c = I2C(1, 50000) # create and init with a 50KHz baudrate
/// i2c.init(100000) # init with a 100KHz baudrate
/// i2c.deinit() # turn off the peripheral
///
/// Printing the i2c object gives you information about its configuration.
///
......@@ -76,7 +76,7 @@
///
/// A master must specify the recipient's address:
///
/// i2c.init(100000)
/// i2c.init(1, 100000)
/// i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
/// i2c.send(b'456', addr=0x42) # keyword for address
///
......@@ -98,6 +98,8 @@ typedef struct _pyb_i2c_obj_t {
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBI2C_MASTER (0)
#define PYBI2C_MIN_BAUD_RATE_HZ (50000)
#define PYBI2C_MAX_BAUD_RATE_HZ (400000)
......@@ -251,16 +253,35 @@ STATIC bool pyb_i2c_scan_device(byte devAddr) {
/******************************************************************************/
/* Micro Python bindings */
/******************************************************************************/
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<I2C1, I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else {
mp_print_str(print, "<I2C1>");
}
}
/// \method init(100000)
/// \method init(mode, *, baudrate=100000)
///
/// Initialise the I2C bus as a master with the given baudrate.
/// Initialise the I2C bus with the given parameters:
///
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_obj_t baudrate) {
pyb_i2c_obj_t *self = self_in;
/// - `mode` must be either `I2C.MASTER` or `I2C.SLAVE`
/// - `baudrate` is the SCL clock rate (only sensible for a master)
STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
};
#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args)
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_I2C_INIT_NUM_ARGS];
mp_arg_parse_all(n_args, args, kw_args, PYB_I2C_INIT_NUM_ARGS, pyb_i2c_init_args, vals);
// make sure the baudrate is between the valid range
self->baudrate = MIN(MAX(mp_obj_get_int(baudrate), PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
self->baudrate = MIN(MAX(vals[1].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
// init the I2C bus
i2c_init(self);
......@@ -273,7 +294,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_obj_t baudrate) {
/// \classmethod \constructor(bus, ...)
///
/// Construct an I2C object on the given bus. `bus` can only be 0.
/// Construct an I2C object on the given bus. `bus` can only be 1.
/// With no additional parameters, the I2C object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any). If extra arguments are given, the bus is initialised.
......@@ -282,32 +303,29 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// work out the i2c bus id
if (mp_obj_get_int(args[0]) != 1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// setup the object
pyb_i2c_obj_t *self = &pyb_i2c_obj;
self->base.type = &pyb_i2c_type;
if (n_args > 0) {
if (n_args > 1 || n_kw > 0) {
// start the peripheral
pyb_i2c_init_helper(self, *args);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_i2c_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return (mp_obj_t)self;
}
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else {
mp_print_str(print, "<I2C0>");
}
STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_i2c_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC mp_obj_t pyb_i2c_init(mp_obj_t self_in, mp_obj_t baudrate) {
return pyb_i2c_init_helper(self_in, baudrate);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_init_obj, pyb_i2c_init);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
/// \method deinit()
/// Turn off the I2C bus.
......@@ -529,6 +547,10 @@ STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_i2c_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_read), (mp_obj_t)&pyb_i2c_mem_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_write), (mp_obj_t)&pyb_i2c_mem_write_obj },
// class constants
/// \constant MASTER - for initialising the bus to master mode
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MASTER) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
......
......@@ -167,24 +167,26 @@ STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
pyb_spi_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<SPI0, SPI.MASTER, baudrate=%u, config=%u, submode=%u, bits=%u>",
self->baudrate, self->config, self->submode, (self->wlen * 8));
mp_printf(print, "<SPI1, SPI.MASTER, baudrate=%u, config=%u, submode=%u, bits=%u>",
self->baudrate, self->config, self->submode, (self->wlen * 8));
}
else {
mp_print_str(print, "<SPI0>");
mp_print_str(print, "<SPI1>");
}
}
/// \method init(2000000, *, bits=8, submode=0, cs=SPI.ACTIVELOW)
/// \method init(mode, *, baudrate=1000000, bits=8, submode=0, cs=SPI.ACTIVELOW)
///
/// Initialise the SPI bus with the given parameters:
///
/// - `mode` must be MASTER.
/// - `baudrate` is the SCK clock rate.
/// - `bits` is the transfer width size (8, 16, 32).
/// - `submode` is the spi mode (0, 1, 2, 3).
/// - `cs` can be ACTIVELOW, ACTIVEHIGH, or NONE
static const mp_arg_t pybspi_init_args[] = {
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_submode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_CS_ACTIVELOW} },
......@@ -195,13 +197,8 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
mp_arg_val_t args[MP_ARRAY_SIZE(pybspi_init_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pybspi_init_args), pybspi_init_args, args);
uint submode = args[2].u_int;
uint cs = args[3].u_int;
uint bits;
// save the word length for later use
self->wlen = args[1].u_int / 8;
switch (args[1].u_int) {
switch (args[2].u_int) {
case 8:
bits = SPI_WL_8;
break;
......@@ -216,16 +213,19 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
break;
}
uint submode = args[3].u_int;
if (submode < SPI_SUB_MODE_0 || submode > SPI_SUB_MODE_3) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
uint cs = args[4].u_int;
if (cs != SPI_CS_ACTIVELOW && cs != SPI_CS_ACTIVEHIGH) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// build the configuration
self->baudrate = args[0].u_int;
self->baudrate = args[1].u_int;
self->wlen = args[2].u_int >> 3;
self->config = bits | cs | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->submode = submode;
......@@ -240,8 +240,8 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
/// \classmethod \constructor(bus, ...)
///
/// Construct an SPI object with the given baudrate.
/// With no parameters, the SPI object is created but not
/// Construct an SPI object with the given baudrate. Bus can only be 1.
/// With no extra parameters, the SPI object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any). If extra arguments are given, the bus is initialised.
/// See `init` for parameters of initialisation.
......@@ -250,14 +250,19 @@ STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// work out the spi bus id
if (mp_obj_get_int(args[0]) != 1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
pyb_spi_obj_t *self = &pyb_spi_obj;
self->base.type = &pyb_spi_type;
if (n_args > 0 || n_kw > 0) {
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_spi_init_helper(self, n_args, args, &kw_args);
pyb_spi_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return self;
......@@ -396,6 +401,7 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_LOW), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVELOW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_HIGH), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVEHIGH) },
};
......
......@@ -60,7 +60,7 @@
///
/// Example usage to toggle an LED at a fixed frequency:
///
/// tim = pyb.Timer(3) # create a timer object using timer 4
/// tim = pyb.Timer(4) # create a timer object using timer 4
/// tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
/// tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
/// tim_ch.callback(handler=lambda t:led.toggle()) # toggle a led on every cycle of the timer
......@@ -68,7 +68,7 @@
/// Further examples:
///
/// tim1 = pyb.Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
/// tim2 = pyb.Timer(0, mode=Timer.PWM) # initialize it in PWM mode
/// tim2 = pyb.Timer(1, mode=Timer.PWM) # initialize it in PWM mode
/// tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the PWM on channel B with a 50% duty cycle
/// tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the event counter with a frequency of 1Hz and triggered by positive edges
/// tim_ch.time() # get the current time in usec (can also be set)
......@@ -303,7 +303,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
default:
break;
}
mp_printf(print, "<Timer%u, mode=Timer.%q>", tim->id, mode_qst);
mp_printf(print, "<Timer%u, mode=Timer.%q>", (tim->id + 1), mode_qst);
}
/// \method init(mode, *, width)
......@@ -360,13 +360,13 @@ error:
/// \classmethod \constructor(id, ...)
/// Construct a new timer object of the given id. If additional
/// arguments are given, then the timer is initialised by `init(...)`.
/// `id` can be 0 to 3
/// `id` can be 1 to 4
STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// create a new Timer object
uint32_t timer_idx = mp_obj_get_int(args[0]);
int32_t timer_idx = mp_obj_get_int(args[0]) - 1;
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
......@@ -579,7 +579,7 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
}
mp_printf(print, "<%q %s, timer=%u, %q=%u", MP_QSTR_TimerChannel,
ch_id, ch->timer->id, MP_QSTR_freq, ch->frequency);
ch_id, (ch->timer->id + 1), MP_QSTR_freq, ch->frequency);
uint32_t mode = ch->timer->config & 0xFF;
if (mode == TIMER_CFG_A_CAP_COUNT || mode == TIMER_CFG_A_CAP_TIME || mode == TIMER_CFG_A_PWM) {
......
......@@ -62,7 +62,7 @@
///
/// from pyb import UART
///
/// uart = UART(0, 9600) # init with given baudrate
/// uart = UART(1, 9600) # init with given baudrate
/// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters
///
/// Bits can be 5, 6, 7, 8, parity can be None, 0 (even), 1 (odd). Stop can be 1 or 2.
......@@ -316,7 +316,7 @@ STATIC void uart_callback_disable (mp_obj_t self_in) {
STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<UART%u, baudrate=%u, bits=", self->uart_id, self->baudrate);
mp_printf(print, "<UART%u, baudrate=%u, bits=", (self->uart_id + 1), self->baudrate);
switch (self->config & UART_CONFIG_WLEN_MASK) {
case UART_CONFIG_WLEN_5:
mp_print_str(print, "5");
......@@ -343,7 +343,7 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
self->timeout, self->timeout_char, self->read_buf_len);
}
else {
mp_printf(print, "<UART%u>", self->uart_id);
mp_printf(print, "<UART%u>", (self->uart_id + 1));
}
}
......@@ -432,7 +432,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
/// \classmethod \constructor(bus, ...)
///
/// Construct a UART object on the given bus id. `bus id` can be 0 or 1
/// Construct a UART object on the given bus id. `bus id` can be 1 or 2
/// With no additional parameters, the UART object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any).
......@@ -448,7 +448,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
mp_arg_check_num(n_args, n_kw, 1, MP_ARRAY_SIZE(pyb_uart_init_args), true);
// work out the uart id
pyb_uart_id_t uart_id = mp_obj_get_int(args[0]);
int32_t uart_id = mp_obj_get_int(args[0]) - 1;
if (uart_id < PYB_UART_0 || uart_id > PYB_UART_1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
......
......@@ -160,6 +160,8 @@ Q(FLOW_TXRX)
// for I2C class
Q(I2C)
Q(mode)
Q(baudrate)
Q(addr)
Q(data)
Q(memaddr)
......@@ -172,6 +174,7 @@ Q(send)
Q(recv)
Q(mem_read)
Q(mem_write)
Q(MASTER)
// for ADC class
Q(ADC)
......@@ -312,6 +315,7 @@ Q(RTC_WAKE)
// for SPI class
Q(SPI)
Q(mode)
Q(baudrate)
Q(bits)
Q(submode)
......@@ -321,6 +325,7 @@ Q(deinit)
Q(send)
Q(recv)
Q(send_recv)
Q(MASTER)
Q(ACTIVE_LOW)
Q(ACTIVE_HIGH)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment