Esempio n. 1
0
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
    byte *p = *ptr;
    mp_uint_t align;

    size_t size = mp_binary_get_size(struct_type, val_type, &align);
    if (struct_type == '@') {
        // Make pointer aligned
        p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
        if (MP_ENDIANNESS_LITTLE) {
            struct_type = '<';
        } else {
            struct_type = '>';
        }
    }
    *ptr = p + size;

    mp_uint_t val;
    switch (val_type) {
        case 'O':
            val = (mp_uint_t)val_in;
            break;
#if MICROPY_PY_BUILTINS_FLOAT
        case 'f': {
            union { uint32_t i; float f; } fp_sp;
            fp_sp.f = mp_obj_get_float(val_in);
            val = fp_sp.i;
            break;
        }
        case 'd': {
            union { uint64_t i64; uint32_t i32[2]; double f; } fp_dp;
            fp_dp.f = mp_obj_get_float(val_in);
            if (BYTES_PER_WORD == 8) {
                val = fp_dp.i64;
            } else {
                int be = struct_type == '>';
                mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]);
                p += sizeof(uint32_t);
                val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be];
            }
            break;
        }
#endif
        default:
            #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
            if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
                mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p);
                return;
            } else
            #endif
            {
                val = mp_obj_get_int(val_in);
                // sign extend if needed
                if (BYTES_PER_WORD < 8 && size > sizeof(val) && is_signed(val_type) && (mp_int_t)val < 0) {
                    memset(p + sizeof(val), 0xff, size - sizeof(val));
                }
            }
    }

    mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val);
}
Esempio n. 2
0
/// \method read_timed(buf, freq)
/// Read analog values into the given buffer at the given frequency. Buffer
/// can be bytearray or array.array for example. If a buffer with 8-bit elements
/// is used, sample resolution will be reduced to 8 bits.
///
/// Example:
///
///     adc = pyb.ADC(pyb.Pin.board.X19)    # create an ADC on pin X19
///     buf = bytearray(100)                # create a buffer of 100 bytes
///     adc.read_timed(buf, 10)             # read analog values into buf at 10Hz
///                                         #   this will take 10 seconds to finish
///     for val in buf:                     # loop over all values
///         print(val)                      # print the value out
///
/// This function does not allocate any memory.
STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) {
    pyb_obj_adc_t *self = self_in;

    mp_buffer_info_t bufinfo;
    mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
    int typesize = mp_binary_get_size('@', bufinfo.typecode, NULL);

    // Init TIM6 at the required frequency (in Hz)
    timer_tim6_init(mp_obj_get_int(freq_in));

    // Start timer
    HAL_TIM_Base_Start(&TIM6_Handle);

    // This uses the timer in polling mode to do the sampling
    // We could use DMA, but then we can't convert the values correctly for the buffer
    adc_config_channel(self);
    for (uint index = 0; index < bufinfo.len; index++) {
        // Wait for the timer to trigger
        while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) {
        }
        __HAL_TIM_CLEAR_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE);
        uint value = adc_read_channel(&self->handle);
        if (typesize == 1) {
            value >>= 4;
        }
        mp_binary_set_val_array_from_int(bufinfo.typecode, bufinfo.buf, index, value);
    }
Esempio n. 3
0
/// \method read_timed(buf, timer)
///
/// Read analog values into `buf` at a rate set by the `timer` object.
///
/// `buf` can be bytearray or array.array for example.  The ADC values have
/// 12-bit resolution and are stored directly into `buf` if its element size is
/// 16 bits or greater.  If `buf` has only 8-bit elements (eg a bytearray) then
/// the sample resolution will be reduced to 8 bits.
///
/// `timer` should be a Timer object, and a sample is read each time the timer
/// triggers.  The timer must already be initialised and running at the desired
/// sampling frequency.
///
/// To support previous behaviour of this function, `timer` can also be an
/// integer which specifies the frequency (in Hz) to sample at.  In this case
/// Timer(6) will be automatically configured to run at the given frequency.
///
/// Example using a Timer object (preferred way):
///
///     adc = pyb.ADC(pyb.Pin.board.X19)    # create an ADC on pin X19
///     tim = pyb.Timer(6, freq=10)         # create a timer running at 10Hz
///     buf = bytearray(100)                # creat a buffer to store the samples
///     adc.read_timed(buf, tim)            # sample 100 values, taking 10s
///
/// Example using an integer for the frequency:
///
///     adc = pyb.ADC(pyb.Pin.board.X19)    # create an ADC on pin X19
///     buf = bytearray(100)                # create a buffer of 100 bytes
///     adc.read_timed(buf, 10)             # read analog values into buf at 10Hz
///                                         #   this will take 10 seconds to finish
///     for val in buf:                     # loop over all values
///         print(val)                      # print the value out
///
/// This function does not allocate any memory.
STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) {
    pyb_obj_adc_t *self = self_in;

    mp_buffer_info_t bufinfo;
    mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
    size_t typesize = mp_binary_get_size('@', bufinfo.typecode, NULL);

    TIM_HandleTypeDef *tim;
    #if defined(TIM6)
    if (mp_obj_is_integer(freq_in)) {
        // freq in Hz given so init TIM6 (legacy behaviour)
        tim = timer_tim6_init(mp_obj_get_int(freq_in));
        HAL_TIM_Base_Start(tim);
    } else
    #endif
    {
        // use the supplied timer object as the sampling time base
        tim = pyb_timer_get_handle(freq_in);
    }

    // configure the ADC channel
    adc_config_channel(&self->handle, self->channel);

    // This uses the timer in polling mode to do the sampling
    // TODO use DMA

    uint nelems = bufinfo.len / typesize;
    for (uint index = 0; index < nelems; index++) {
        // Wait for the timer to trigger so we sample at the correct frequency
        while (__HAL_TIM_GET_FLAG(tim, TIM_FLAG_UPDATE) == RESET) {
        }
        __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE);

        if (index == 0) {
            // for the first sample we need to turn the ADC on
            HAL_ADC_Start(&self->handle);
        } else {
            // for subsequent samples we can just set the "start sample" bit
#if defined(STM32F4) || defined(STM32F7)
            ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#elif defined(STM32L4)
            SET_BIT(ADCx->CR, ADC_CR_ADSTART);
#else
            #error Unsupported processor
#endif
        }

        // wait for sample to complete
        #define READ_TIMED_TIMEOUT (10) // in ms
        adc_wait_for_eoc_or_timeout(READ_TIMED_TIMEOUT);

        // read value
        uint value = ADCx->DR;

        // store value in buffer
        if (typesize == 1) {
            value >>= 4;
        }
        mp_binary_set_val_array_from_int(bufinfo.typecode, bufinfo.buf, index, value);
    }
Esempio n. 4
0
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
    byte *p = *ptr;
    mp_uint_t align;

    int size = mp_binary_get_size(struct_type, val_type, &align);
    if (struct_type == '@') {
        // Make pointer aligned
        p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
        #if MP_ENDIANNESS_LITTLE
        struct_type = '<';
        #else
        struct_type = '>';
        #endif
    }
    *ptr = p + size;

    mp_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);

    if (val_type == 'O') {
        return (mp_obj_t)val;
    } else if (val_type == 'S') {
        return mp_obj_new_str((char*)val, strlen((char*)val), false);
    } else if (is_signed(val_type)) {
        return mp_obj_new_int(val);
    } else {
        return mp_obj_new_int_from_uint(val);
    }
}
Esempio n. 5
0
STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
    const char *fmt = mp_obj_str_get_str(fmt_in);
    char fmt_type = get_fmt_type(&fmt);
    machine_uint_t size;
    for (size = 0; *fmt; fmt++) {
        uint align;
        machine_uint_t cnt = 1;
        if (unichar_isdigit(*fmt)) {
            cnt = get_fmt_num(&fmt);
        }
        if (cnt > 1) {
            // TODO: count spec support only for string len
            assert(*fmt == 's');
        }

        machine_uint_t sz;
        if (*fmt == 's') {
            sz = cnt;
        } else {
            sz = (machine_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
        }
        // TODO
        assert(sz != (machine_uint_t)-1);
        // Apply alignment
        size = (size + align - 1) & ~(align - 1);
        size += sz;
    }
    return MP_OBJ_NEW_SMALL_INT(size);
}
Esempio n. 6
0
STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
    // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
    assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray))
        || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));
    mp_obj_array_t *self = self_in;

    // allow to extend by anything that has the buffer protocol (extension to CPython)
    mp_buffer_info_t arg_bufinfo;
    mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ);

    size_t sz = mp_binary_get_size('@', self->typecode, NULL);

    // convert byte count to element count
    mp_uint_t len = arg_bufinfo.len / sz;

    // make sure we have enough room to extend
    // TODO: alloc policy; at the moment we go conservative
    if (self->free < len) {
        self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz);
        self->free = 0;
    } else {
        self->free -= len;
    }

    // extend
    mp_seq_copy((byte*)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte);
    self->len += len;

    return mp_const_none;
}
Esempio n. 7
0
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
    mp_obj_array_t *o = o_in;
    bufinfo->buf = o->items;
    bufinfo->len = o->len * mp_binary_get_size('@', o->typecode, NULL);
    bufinfo->typecode = o->typecode;
    return 0;
}
Esempio n. 8
0
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
    byte *p = *ptr;
    mp_uint_t align;

    int size = mp_binary_get_size(struct_type, val_type, &align);
    if (struct_type == '@') {
        // Make pointer aligned
        p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
        #if MP_ENDIANNESS_LITTLE
        struct_type = '<';
        #else
        struct_type = '>';
        #endif
    }
    *ptr = p + size;

#if MP_ENDIANNESS_BIG
#error Not implemented
#endif
    mp_int_t val;
    byte *in = (byte*)&val;
    switch (val_type) {
        case 'O':
            in = (byte*)&val_in;
            break;
        default:
            val = mp_obj_get_int(val_in);
    }

    mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, in);
}
Esempio n. 9
0
STATIC mp_obj_array_t *array_new(char typecode, uint n) {
    mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
    o->base.type = &array_type;
    o->typecode = typecode;
    o->free = 0;
    o->len = n;
    o->items = m_malloc(mp_binary_get_size(typecode) * o->len);
    return o;
}
Esempio n. 10
0
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
    byte *p = *ptr;
    mp_uint_t align;

    int size = mp_binary_get_size(struct_type, val_type, &align);
    if (struct_type == '@') {
        // Make pointer aligned
        p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
        if (MP_ENDIANNESS_LITTLE) {
            struct_type = '<';
        } else {
            struct_type = '>';
        }
    }
    *ptr = p + size;

    mp_uint_t val;
    switch (val_type) {
        case 'O':
            val = (mp_uint_t)val_in;
            break;
#if MICROPY_PY_BUILTINS_FLOAT
        case 'f': {
            union { uint32_t i; float f; } fp_sp;
            fp_sp.f = mp_obj_get_float(val_in);
            val = fp_sp.i;
            break;
        }
        case 'd': {
            union { uint64_t i64; uint32_t i32[2]; double f; } fp_dp;
            fp_dp.f = mp_obj_get_float(val_in);
            if (BYTES_PER_WORD == 8) {
                val = fp_dp.i64;
            } else {
                int be = struct_type == '>';
                mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]);
                p += sizeof(uint32_t);
                val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be];
            }
            break;
        }
#endif
        default:
            // we handle large ints here by calling the truncated accessor
            if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
                val = mp_obj_int_get_truncated(val_in);
            } else {
                val = mp_obj_get_int(val_in);
            }
    }

    mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val);
}
Esempio n. 11
0
/// \method read_timed(buf, freq)
/// Read analog values into the given buffer at the given frequency. Buffer
/// can be bytearray or array.array for example. If a buffer with 8-bit elements
/// is used, sample resolution will be reduced to 8 bits.
///
/// Example:
///
///     adc = pyb.ADC(pyb.Pin.board.X19)    # create an ADC on pin X19
///     buf = bytearray(100)                # create a buffer of 100 bytes
///     adc.read_timed(buf, 10)             # read analog values into buf at 10Hz
///                                         #   this will take 10 seconds to finish
///     for val in buf:                     # loop over all values
///         print(val)                      # print the value out
///
/// This function does not allocate any memory.
STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) {
    pyb_obj_adc_t *self = self_in;

    mp_buffer_info_t bufinfo;
    mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
    int typesize = mp_binary_get_size('@', bufinfo.typecode, NULL);

    // Init TIM6 at the required frequency (in Hz)
    timer_tim6_init(mp_obj_get_int(freq_in));

    // Start timer
    HAL_TIM_Base_Start(&TIM6_Handle);

    // configure the ADC channel
    adc_config_channel(self);

    // This uses the timer in polling mode to do the sampling
    // TODO use DMA

    uint nelems = bufinfo.len / typesize;
    for (uint index = 0; index < nelems; index++) {
        // Wait for the timer to trigger so we sample at the correct frequency
        while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) {
        }
        __HAL_TIM_CLEAR_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE);

        if (index == 0) {
            // for the first sample we need to turn the ADC on
            HAL_ADC_Start(&self->handle);
        } else {
            // for subsequent samples we can just set the "start sample" bit
            ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
        }

        // wait for sample to complete
        uint32_t tickstart = HAL_GetTick();
        while ((ADCx->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) {
            #define READ_TIMED_TIMEOUT (10) // in ms
            if (((HAL_GetTick() - tickstart ) > READ_TIMED_TIMEOUT)) {
                break; // timeout
            }
        }

        // read value
        uint value = ADCx->DR;

        // store value in buffer
        if (typesize == 1) {
            value >>= 4;
        }
        mp_binary_set_val_array_from_int(bufinfo.typecode, bufinfo.buf, index, value);
    }
Esempio n. 12
0
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
    int typecode_size = mp_binary_get_size('@', typecode, NULL);
    if (typecode_size <= 0) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode"));
    }
    mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
    o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
    o->typecode = typecode;
    o->free = 0;
    o->len = n;
    o->items = m_malloc(typecode_size * o->len);
    return o;
}
Esempio n. 13
0
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
    assert(MP_OBJ_IS_TYPE(self_in, &array_type));
    mp_obj_array_t *self = self_in;
    if (self->free == 0) {
        int item_sz = mp_binary_get_size(self->typecode);
        // TODO: alloc policy
        self->free = 8;
        self->items = m_realloc(self->items,  item_sz * self->len, item_sz * (self->len + self->free));
    }
    mp_binary_set_val(self->typecode, self->items, self->len++, arg);
    self->free--;
    return mp_const_none; // return None, as per CPython
}
Esempio n. 14
0
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
    // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
    assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray))
        || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));
    mp_obj_array_t *self = self_in;

    if (self->free == 0) {
        size_t item_sz = mp_binary_get_size('@', self->typecode, NULL);
        // TODO: alloc policy
        self->free = 8;
        self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free));
        mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz);
    }
    mp_binary_set_val_array(self->typecode, self->items, self->len++, arg);
    self->free--;
    return mp_const_none; // return None, as per CPython
}
Esempio n. 15
0
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
    mp_obj_array_t *o = o_in;
    size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
    bufinfo->buf = o->items;
    bufinfo->len = o->len * sz;
    bufinfo->typecode = o->typecode & TYPECODE_MASK;
    #if MICROPY_PY_BUILTINS_MEMORYVIEW
    if (o->base.type == &mp_type_memoryview) {
        if ((o->typecode & 0x80) == 0 && (flags & MP_BUFFER_WRITE)) {
            // read-only memoryview
            return 1;
        }
        bufinfo->buf = (uint8_t*)bufinfo->buf + (mp_uint_t)o->free * sz;
    }
    #endif
    return 0;
}
Esempio n. 16
0
STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
    mp_obj_array_t *lhs = lhs_in;
    switch (op) {
        case MP_BINARY_OP_ADD: {
            // allow to add anything that has the buffer protocol (extension to CPython)
            mp_buffer_info_t lhs_bufinfo;
            mp_buffer_info_t rhs_bufinfo;
            array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
            mp_get_buffer_raise(rhs_in, &rhs_bufinfo, MP_BUFFER_READ);

            size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL);

            // convert byte count to element count (in case rhs is not multiple of sz)
            mp_uint_t rhs_len = rhs_bufinfo.len / sz;

            // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count
            mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len);
            mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte);
            return res;
        }

        case MP_BINARY_OP_INPLACE_ADD: {
            #if MICROPY_PY_BUILTINS_MEMORYVIEW
            if (lhs->base.type == &mp_type_memoryview) {
                return MP_OBJ_NULL; // op not supported
            }
            #endif
            array_extend(lhs, rhs_in);
            return lhs;
        }

        case MP_BINARY_OP_EQUAL: {
            mp_buffer_info_t lhs_bufinfo;
            mp_buffer_info_t rhs_bufinfo;
            array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
            if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
                return mp_const_false;
            }
            return MP_BOOL(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len));
        }

        default:
            return MP_OBJ_NULL; // op not supported
    }
}
Esempio n. 17
0
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
    byte *p = *ptr;
    mp_uint_t align;

    size_t size = mp_binary_get_size(struct_type, val_type, &align);
    if (struct_type == '@') {
        // Make pointer aligned
        p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
        #if MP_ENDIANNESS_LITTLE
        struct_type = '<';
        #else
        struct_type = '>';
        #endif
    }
    *ptr = p + size;

    long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);

    if (val_type == 'O') {
        return (mp_obj_t)(mp_uint_t)val;
    } else if (val_type == 'S') {
        const char *s_val = (const char*)(mp_uint_t)val;
        return mp_obj_new_str(s_val, strlen(s_val), false);
#if MICROPY_PY_BUILTINS_FLOAT
    } else if (val_type == 'f') {
        union { uint32_t i; float f; } fpu = {val};
        return mp_obj_new_float(fpu.f);
    } else if (val_type == 'd') {
        union { uint64_t i; double f; } fpu = {val};
        return mp_obj_new_float(fpu.f);
#endif
    } else if (is_signed(val_type)) {
        if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) {
            return mp_obj_new_int((mp_int_t)val);
        } else {
            return mp_obj_new_int_from_ll(val);
        }
    } else {
        if ((unsigned long long)val <= (unsigned long long)MP_SMALL_INT_MAX) {
            return mp_obj_new_int_from_uint((mp_uint_t)val);
        } else {
            return mp_obj_new_int_from_ull(val);
        }
    }
}
Esempio n. 18
0
STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
    // bytearrays can be raw-initialised from anything with the buffer protocol
    // other arrays can only be raw-initialised from bytes and bytearray objects
    mp_buffer_info_t bufinfo;
    if (((MICROPY_PY_BUILTINS_BYTEARRAY
            && typecode == BYTEARRAY_TYPECODE)
        || (MICROPY_PY_ARRAY
            && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes)
                || (MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(initializer, &mp_type_bytearray)))))
        && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) {
        // construct array from raw bytes
        // we round-down the len to make it a multiple of sz (CPython raises error)
        size_t sz = mp_binary_get_size('@', typecode, NULL);
        mp_uint_t len = bufinfo.len / sz;
        mp_obj_array_t *o = array_new(typecode, len);
        memcpy(o->items, bufinfo.buf, len * sz);
        return o;
    }

    mp_uint_t len;
    // Try to create array of exact len if initializer len is known
    mp_obj_t len_in = mp_obj_len_maybe(initializer);
    if (len_in == MP_OBJ_NULL) {
        len = 0;
    } else {
        len = MP_OBJ_SMALL_INT_VALUE(len_in);
    }

    mp_obj_array_t *array = array_new(typecode, len);

    mp_obj_t iterable = mp_getiter(initializer);
    mp_obj_t item;
    mp_uint_t i = 0;
    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
        if (len == 0) {
            array_append(array, item);
        } else {
            mp_binary_set_val_array(typecode, array->items, i++, item);
        }
    }

    return array;
}
Esempio n. 19
0
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
    int typecode_size = mp_binary_get_size('@', typecode, NULL);
    if (typecode_size == 0) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode"));
    }
    mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
    #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
    o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
    #elif MICROPY_PY_BUILTINS_BYTEARRAY
    o->base.type = &mp_type_bytearray;
    #else
    o->base.type = &mp_type_array;
    #endif
    o->typecode = typecode;
    o->free = 0;
    o->len = n;
    o->items = m_new(byte, typecode_size * o->len);
    return o;
}
Esempio n. 20
0
STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
    if (value == MP_OBJ_NULL) {
        // delete item
        // TODO implement
        // TODO: confirmed that both bytearray and array.array support
        // slice deletion
        return MP_OBJ_NULL; // op not supported
    } else {
        mp_obj_array_t *o = self_in;
        if (0) {
#if MICROPY_PY_BUILTINS_SLICE
        } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
            if (value != MP_OBJ_SENTINEL) {
                // Only getting a slice is suported so far, not assignment
                // TODO: confirmed that both bytearray and array.array support
                // slice assignment (incl. of different size)
                return MP_OBJ_NULL; // op not supported
            }
            mp_bound_slice_t slice;
            if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
                nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
                    "only slices with step=1 (aka None) are supported"));
            }
            mp_obj_array_t *res = array_new(o->typecode, slice.stop - slice.start);
            int sz = mp_binary_get_size('@', o->typecode, NULL);
            assert(sz > 0);
            byte *p = o->items;
            memcpy(res->items, p + slice.start * sz, (slice.stop - slice.start) * sz);
            return res;
#endif
        } else {
            uint index = mp_get_index(o->base.type, o->len, index_in, false);
            if (value == MP_OBJ_SENTINEL) {
                // load
                return mp_binary_get_val_array(o->typecode, o->items, index);
            } else {
                // store
                mp_binary_set_val_array(o->typecode, o->items, index, value);
                return mp_const_none;
            }
        }
    }
}
Esempio n. 21
0
STATIC mp_obj_t memoryview_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
    (void)type_in;

    // TODO possibly allow memoryview constructor to take start/stop so that one
    // can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM)

    mp_arg_check_num(n_args, n_kw, 1, 1, false);

    mp_buffer_info_t bufinfo;
    mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);

    mp_obj_array_t *self = mp_obj_new_memoryview(bufinfo.typecode,
        bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL),
        bufinfo.buf);

    // test if the object can be written to
    if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
        self->typecode |= 0x80; // used to indicate writable buffer
    }

    return self;
}
Esempio n. 22
0
STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
    if (value == MP_OBJ_NULL) {
        // delete item
        // TODO implement
        // TODO: confirmed that both bytearray and array.array support
        // slice deletion
        return MP_OBJ_NULL; // op not supported
    } else {
        mp_obj_array_t *o = self_in;
        if (0) {
#if MICROPY_PY_BUILTINS_SLICE
        } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
            mp_bound_slice_t slice;
            if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
                mp_not_implemented("only slices with step=1 (aka None) are supported");
            }
            if (value != MP_OBJ_SENTINEL) {
                #if MICROPY_PY_ARRAY_SLICE_ASSIGN
                // Assign
                mp_uint_t src_len;
                void *src_items;
                size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
                if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)value)->type->subscr == array_subscr) {
                    // value is array, bytearray or memoryview
                    mp_obj_array_t *src_slice = value;
                    if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
                    compat_error:
                        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible"));
                    }
                    src_len = src_slice->len;
                    src_items = src_slice->items;
                    #if MICROPY_PY_BUILTINS_MEMORYVIEW
                    if (MP_OBJ_IS_TYPE(value, &mp_type_memoryview)) {
                        src_items = (uint8_t*)src_items + (src_slice->free * item_sz);
                    }
                    #endif
                } else if (MP_OBJ_IS_TYPE(value, &mp_type_bytes)) {
                    if (item_sz != 1) {
                        goto compat_error;
                    }
                    mp_buffer_info_t bufinfo;
                    mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ);
                    src_len = bufinfo.len;
                    src_items = bufinfo.buf;
                } else {
                    mp_not_implemented("array/bytes required on right side");
                }

                // TODO: check src/dst compat
                mp_int_t len_adj = src_len - (slice.stop - slice.start);
                uint8_t* dest_items = o->items;
                #if MICROPY_PY_BUILTINS_MEMORYVIEW
                if (o->base.type == &mp_type_memoryview) {
                    if (len_adj != 0) {
                        goto compat_error;
                    }
                    dest_items += o->free * item_sz;
                }
                #endif
                if (len_adj > 0) {
                    if (len_adj > o->free) {
                        // TODO: alloc policy; at the moment we go conservative
                        o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
                        o->free = 0;
                    }
                    mp_seq_replace_slice_grow_inplace(dest_items, o->len,
                        slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
                } else {
                    mp_seq_replace_slice_no_grow(dest_items, o->len,
                        slice.start, slice.stop, src_items, src_len, item_sz);
                    // Clear "freed" elements at the end of list
                    // TODO: This is actually only needed for typecode=='O'
                    mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);
                    // TODO: alloc policy after shrinking
                }
                o->len += len_adj;
                return mp_const_none;
                #else
                return MP_OBJ_NULL; // op not supported
                #endif
            }

            mp_obj_array_t *res;
            size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
            assert(sz > 0);
            if (0) {
                // dummy
            #if MICROPY_PY_BUILTINS_MEMORYVIEW
            } else if (o->base.type == &mp_type_memoryview) {
                res = m_new_obj(mp_obj_array_t);
                *res = *o;
                res->free += slice.start;
                res->len = slice.stop - slice.start;
            #endif
            } else {
                res = array_new(o->typecode, slice.stop - slice.start);
                memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);
            }
            return res;
#endif
        } else {
            mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false);
            #if MICROPY_PY_BUILTINS_MEMORYVIEW
            if (o->base.type == &mp_type_memoryview) {
                index += o->free;
                if (value != MP_OBJ_SENTINEL && (o->typecode & 0x80) == 0) {
                    // store to read-only memoryview
                    return MP_OBJ_NULL;
                }
            }
            #endif
            if (value == MP_OBJ_SENTINEL) {
                // load
                return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index);
            } else {
                // store
                mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value);
                return mp_const_none;
            }
        }
    }
}
Esempio n. 23
0
STATIC machine_int_t array_get_buffer(mp_obj_t o_in, buffer_info_t *bufinfo, int flags) {
    mp_obj_array_t *o = o_in;
    bufinfo->buf = o->items;
    bufinfo->len = o->len * mp_binary_get_size(o->typecode);
    return 0;
}