How to get uint(uint16_t) from arg?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
turoksama
Posts: 12
Joined: Sun Mar 31, 2019 8:49 am

How to get uint(uint16_t) from arg?

Post by turoksama » Sun Jun 16, 2019 3:57 pm

Hi there,
How can I get uint integer from arg?
int c = mp_obj_get_int(args[5]);
when i use the variable c that fit into uint16_t, i think it will discard values greater than 32767....
............ :?:

User avatar
jimmo
Posts: 648
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: How to get uint(uint16_t) from arg?

Post by jimmo » Sun Jun 16, 2019 10:24 pm

Can you explain what you mean in more detail? Or perhaps an example showing the problem you're seeing?

You should just be able to write

Code: Select all

int a = mp_obj_get_int(args[5]);
uint16_t b = a;
If a is in the range [0, 65535] then b will have the same value. If a is negative or greater than 65535 then you'll see problems.

turoksama
Posts: 12
Joined: Sun Mar 31, 2019 8:49 am

Re: How to get uint(uint16_t) from arg?

Post by turoksama » Mon Jun 17, 2019 5:06 am

jimmo wrote:
Sun Jun 16, 2019 10:24 pm
Can you explain what you mean in more detail? Or perhaps an example showing the problem you're seeing?

You should just be able to write

Code: Select all

int a = mp_obj_get_int(args[5]);
uint16_t b = a;
If a is in the range [0, 65535] then b will have the same value. If a is negative or greater than 65535 then you'll see problems.
Hmm, something like that. So, the type of keyword int in micropython is 4-byte long. I made a mistake about it before( i traced into header file, and it says somewhat like #define int +2, i thought it was a 2-byte long type).

Here I have a very strange behavior like this:

I ported an 18-bit TFT LCD to micropython as type of micropython, which i modified lcd.c to do that.
The color system is 16-bit(RGB565), a 3-byte rgb data can only be accept by the lcd , so, I have to use a buffer to store the expanded color bytes( RGB565 -> RGB888 ) , and then transfer.
For example, I defined a buffer for 8 lines of lcd: uint8_t buf[8*LCD_WIDTH*3].
I tested 16 lines of filling, tranfer twice will do.
Same driver codes in 2 software platforms:
In micropython run:
the color of the first 8 lines was always not correct with values > 0x00ff, but the later 8 is correct, for example: color 0xffff should be white, but the first 8 lines will show somewhat grey, the rest shows white.
1-byte colors are not correct too, except 0x0000-BLACK.
The most tricky thing is the content of the buffer never be touched again once caculated!
In naked run:
the color of all lines was always correct!

Code: Select all

void lcd_dev_fill_rect_mono(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
{
	uint32_t size, i;
	uint16_t d, m;
	uint8_t  rgb_buf[8*LCD_WIDTH*3];

	size = (y1 - y0 + 1) * (x1 - x0 + 1);

	lcd_dev_set_window(x0, y0, x1, y1);
	lcd_dev_xfer_cmd(MONITOR_WRITE_PIXELS);

	uint8_t rgb[3];
	uint32_t t;
	rgb[0] = (color >> 8) & 0xF8;
	rgb[1] = (color >> 3) & 0xFC;
	rgb[2] = color << 3;
	for (i = 0; i < 8*LCD_WIDTH; i++)
	{
		rgb_buf[i * 3 + 0] = rgb[0];
		rgb_buf[i * 3 + 1] = rgb[1];
		rgb_buf[i * 3 + 2] = rgb[2];
	}
	d = size/(8*LCD_WIDTH);//block
	m = size%(8*LCD_WIDTH);//rest
	for(i = 0; i < d; i++)
	{
		lcd_dev_xfer_data(rgb_buf, 8*LCD_WIDTH*3);
	}
	lcd_dev_xfer_data(rgb_buf, m*3);
}

/// \method fill(colour)
///
/// Fill the screen with the given colour (0 or 1 for white or black).
///
/// This method writes to the hidden buffer.  Use `show()` to show the buffer.
STATIC mp_obj_t pyb_lcd_fill(size_t n_args, const mp_obj_t *args)
{
    pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]);
    int x0 = mp_obj_get_int(args[1]);
    int y0 = mp_obj_get_int(args[2]);
    int x1 = mp_obj_get_int(args[3]);
    int y1 = mp_obj_get_int(args[4]);
	int c  = mp_obj_get_int(args[5]);

	/*Truncate the area to the screen*/
	int xt0 = x0 < 0 ? 0 : x0;
	int yt0 = y0 < 0 ? 0 : y0;
	int xt1 = x1 > self->width  ? self->width  : x1;
	int yt1 = y1 > self->height ? self->height : y1;

	/*Return if the area is out the screen*/
	lcd_dev_fill_rect_mono(xt0,yt0,xt1,yt1,c);

	return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_lcd_fill_obj, 6, 6, pyb_lcd_fill);
Micropython test code: (LCD WIDTH = 320)

Code: Select all

>>>pyb.lcd.fill(0,0,319,15,0xffff)
not correct.

Code: Select all

>>>pyb.lcd.fill(0,0,319,15,0x00ff)
correct.

I noticed a configuration in /py/mpconfig.h, lines 108-110:

Code: Select all

// A MicroPython object is a machine word having the following form:
//  - xxxx...xxx1 : a small int, bits 1 and above are the value
//  - xxxx...xx10 : a qstr, bits 2 and above are the value
//  - xxxx...xx00 : a pointer to an mp_obj_base_t (unless a fake object)
#define MICROPY_OBJ_REPR_A (0)

... ...

#ifndef MICROPY_OBJ_REPR
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
#endif
Well, may it be the one?
I will test it later.

Well, #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) with no luck...

Post Reply