Compare commits

..

18 Commits
v1.1 ... v1.1.1

Author SHA1 Message Date
Damien George
2547928148 stmhal: Add Python function to set UART for REPL.
This adds a hook to get/set pyb_uart_global_debug from Python, using
pyb.repl_uart().  You can set it to an arbitrary UART object, and then
the REPL (in and out) is repeated on this UART object (as well as on USB
CDC).

Ultimately, this will be replaced with a proper Pythonic interface to
set sys.stdin and sys.stdout.
2014-06-15 09:47:27 +01:00
Damien George
c0711cbefa stmhal: Fix type signatures on functions that take variable args. 2014-06-15 09:32:42 +01:00
Damien George
e79c6696c5 stmhal: Fix file print methods to use print instead of printf.
Also make stdout_print_strn static (ultimately this function needs to be
merged with stdout_tx_strn).
2014-06-15 09:10:07 +01:00
Damien George
34ab8dd6dd stmhal: Update and improve LCD driver.
Still some method names to iron out, and funtionality to add, but this
will do for the first, basic version.
2014-06-15 00:41:47 +01:00
Paul Sokolovsky
0294661da5 parsenum: Signedness issues.
char can be signedness, and using signedness types is dangerous - it can
lead to negative offsets when doing table lookups. We apparently should just
ban char usage.
2014-06-14 18:02:21 +03:00
Damien George
812025bd83 Merge pull request #693 from iabdalkader/assert
Add __assert_func
2014-06-14 15:51:40 +01:00
mux
5f6f47a688 Make __assert_func weak 2014-06-14 17:02:50 +02:00
mux
00db5c81e1 Add __assert_func only if DEBUG=1 2014-06-14 15:53:11 +02:00
mux
34e7b67d3c Add __assert_func
* issue #692
2014-06-14 14:41:11 +02:00
Paul Sokolovsky
e3cfc0d33d objstr: Refactor to work with char pointers instead of indexes.
In preparation for unicode support.
2014-06-14 06:30:30 +03:00
Paul Sokolovsky
7ddbd1bee7 unicode: Add trivial implementation of unichar_charlen(). 2014-06-14 06:30:30 +03:00
Paul Sokolovsky
b0bb458810 unicode: String API is const byte*.
We still have that char vs byte dichotomy, but majority of string operations
now use byte.
2014-06-14 06:22:11 +03:00
Paul Sokolovsky
2ec38a17d4 objstr: Be 8-bit clean even for repr().
This will allow roughly the same behavior as Python3 for non-ASCII strings,
for example, print("<phrase in non-Latin script>".split()) will print list
of words, not weird hex dump (like Python2 behaves). (Of course, that it
will print list of words, if there're "words" in that phrase at all, separated
by ASCII-compatible whitespace; that surely won't apply to every human
language in existence).
2014-06-14 01:21:13 +03:00
Damien George
e9036c295c Merge branch 'stinos-gc-pointers' 2014-06-13 22:34:11 +01:00
Damien George
c037694957 py, gc: Revert ret_ptr to void*, casting to byte* for memset. 2014-06-13 22:33:31 +01:00
Damien George
63b2237323 Merge branch 'gc-pointers' of github.com:stinos/micropython into stinos-gc-pointers 2014-06-13 22:30:46 +01:00
Paul Sokolovsky
e22cddbe2a stream: Use mp_obj_is_true() for EOF testing.
Getting a length of string may be expensive, depending on the underlying
implementation.
2014-06-13 23:53:10 +03:00
stijn
f33385f56d gc: Use byte* pointers instead of void* for pointer arithmetic
void* is of unknown size
2014-06-13 20:42:06 +02:00
20 changed files with 508 additions and 407 deletions

10
py/gc.c
View File

@@ -120,7 +120,7 @@ void gc_init(void *start, void *end) {
// F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB
// P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK
// => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK)
machine_uint_t total_byte_len = end - start;
machine_uint_t total_byte_len = (byte*)end - (byte*)start;
#if MICROPY_ENABLE_FINALISER
gc_alloc_table_byte_len = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK);
#else
@@ -136,8 +136,8 @@ void gc_init(void *start, void *end) {
#endif
machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
gc_pool_start = end - gc_pool_block_len * BYTES_PER_BLOCK;
gc_pool_end = end;
gc_pool_start = (machine_uint_t*)((byte*)end - gc_pool_block_len * BYTES_PER_BLOCK);
gc_pool_end = (machine_uint_t*)end;
// clear ATBs
memset(gc_alloc_table_start, 0, gc_alloc_table_byte_len);
@@ -407,7 +407,7 @@ found:
// to the heap and will not be set to something else if the caller
// doesn't actually use the entire block. As such they will continue
// to point to the heap and may prevent other blocks from being reclaimed.
memset(ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
#if MICROPY_ENABLE_FINALISER
if (has_finaliser) {
@@ -571,7 +571,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
}
// zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)
memset(ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
return ptr_in;
}

View File

@@ -83,8 +83,8 @@ bool str_strn_equal(const char *str, const char *strn, int len) {
void mp_token_show(const mp_token_t *tok) {
printf("(%d:%d) kind:%d str:%p len:%d", tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
if (tok->str != NULL && tok->len > 0) {
const char *i = tok->str;
const char *j = i + tok->len;
const byte *i = (const byte *)tok->str;
const byte *j = (const byte *)i + tok->len;
printf(" ");
while (i < j) {
unichar c = utf8_get_char(i);

View File

@@ -88,8 +88,8 @@ int m_get_peak_bytes_allocated(void);
typedef int unichar; // TODO
unichar utf8_get_char(const char *s);
char *utf8_next_char(const char *s);
unichar utf8_get_char(const byte *s);
const byte *utf8_next_char(const byte *s);
bool unichar_isspace(unichar c);
bool unichar_isalpha(unichar c);
@@ -100,6 +100,7 @@ bool unichar_isupper(unichar c);
bool unichar_islower(unichar c);
unichar unichar_tolower(unichar c);
unichar unichar_toupper(unichar c);
#define unichar_charlen(s, bytelen) (bytelen)
/** variable string *********************************************/

View File

@@ -469,7 +469,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str);
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len);
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT
// float

View File

@@ -58,7 +58,7 @@ STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *en
mp_obj_array_t *o = o_in;
if (o->typecode == BYTEARRAY_TYPECODE) {
print(env, "bytearray(b", o->typecode);
mp_str_print_quoted(print, env, o->items, o->len);
mp_str_print_quoted(print, env, o->items, o->len, true);
} else {
print(env, "array('%c'", o->typecode);
if (o->len > 0) {

View File

@@ -64,7 +64,8 @@ STATIC bool is_str_or_bytes(mp_obj_t o) {
/******************************************************************************/
/* str */
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env,
const byte *str_data, uint str_len, bool is_bytes) {
// this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false;
bool has_double_quote = false;
@@ -85,7 +86,10 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
print(env, "\\%c", quote_char);
} else if (*s == '\\') {
print(env, "\\\\");
} else if (32 <= *s && *s <= 126) {
} else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) {
// In strings, anything which is not ascii control character
// is printed as is, this includes characters in range 0x80-0xff
// (which can be non-Latin letters, etc.)
print(env, "%c", *s);
} else if (*s == '\n') {
print(env, "\\n");
@@ -109,7 +113,7 @@ STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env,
if (is_bytes) {
print(env, "b");
}
mp_str_print_quoted(print, env, str_data, str_len);
mp_str_print_quoted(print, env, str_data, str_len, is_bytes);
}
}
@@ -348,6 +352,12 @@ uncomparable:
return MP_OBJ_NULL; // op not supported
}
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
mp_obj_t index, bool is_slice) {
machine_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
return self_data + index_val;
}
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_type_t *type = mp_obj_get_type(self_in);
GET_STR_DATA_LEN(self_in, self_data, self_len);
@@ -363,11 +373,11 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start);
}
#endif
uint index_val = mp_get_index(type, self_len, index, false);
const byte *p = str_index_to_ptr(type, self_data, self_len, index, false);
if (type == &mp_type_bytes) {
return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self_data[index_val]);
return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)*p);
} else {
return mp_obj_new_str((char*)self_data + index_val, 1, true);
return mp_obj_new_str((char*)p, 1, true);
}
} else {
return MP_OBJ_NULL; // op not supported
@@ -563,6 +573,7 @@ STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) {
STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t direction, bool is_index) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_STR(args[0]));
assert(MP_OBJ_IS_STR(args[1]));
@@ -570,16 +581,16 @@ STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t dire
GET_STR_DATA_LEN(args[0], haystack, haystack_len);
GET_STR_DATA_LEN(args[1], needle, needle_len);
machine_uint_t start = 0;
machine_uint_t end = haystack_len;
const byte *start = haystack;
const byte *end = haystack + haystack_len;
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&mp_type_str, haystack_len, args[2], true);
start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);
}
if (n_args >= 4 && args[3] != mp_const_none) {
end = mp_get_index(&mp_type_str, haystack_len, args[3], true);
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
}
const byte *p = find_subbytes(haystack + start, end - start, needle, needle_len, direction);
const byte *p = find_subbytes(start, end - start, needle, needle_len, direction);
if (p == NULL) {
// not found
if (is_index) {
@@ -611,16 +622,17 @@ STATIC mp_obj_t str_rindex(uint n_args, const mp_obj_t *args) {
// TODO: (Much) more variety in args
STATIC mp_obj_t str_startswith(uint n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
GET_STR_DATA_LEN(args[0], str, str_len);
GET_STR_DATA_LEN(args[1], prefix, prefix_len);
uint index_val = 0;
const byte *start = str;
if (n_args > 2) {
index_val = mp_get_index(&mp_type_str, str_len, args[2], true);
start = str_index_to_ptr(self_type, str, str_len, args[2], true);
}
if (prefix_len + index_val > str_len) {
if (prefix_len + (start - str) > str_len) {
return mp_const_false;
}
return MP_BOOL(memcmp(str + index_val, prefix, prefix_len) == 0);
return MP_BOOL(memcmp(start, prefix, prefix_len) == 0);
}
STATIC mp_obj_t str_endswith(uint n_args, const mp_obj_t *args) {
@@ -1418,6 +1430,7 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
}
STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_STR(args[0]));
assert(MP_OBJ_IS_STR(args[1]));
@@ -1425,26 +1438,28 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
GET_STR_DATA_LEN(args[0], haystack, haystack_len);
GET_STR_DATA_LEN(args[1], needle, needle_len);
machine_uint_t start = 0;
machine_uint_t end = haystack_len;
const byte *start = haystack;
const byte *end = haystack + haystack_len;
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&mp_type_str, haystack_len, args[2], true);
start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);
}
if (n_args >= 4 && args[3] != mp_const_none) {
end = mp_get_index(&mp_type_str, haystack_len, args[3], true);
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
}
// if needle_len is zero then we count each gap between characters as an occurrence
if (needle_len == 0) {
return MP_OBJ_NEW_SMALL_INT(end - start + 1);
return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char*)start, end - start) + 1);
}
// count the occurrences
machine_int_t num_occurrences = 0;
for (machine_uint_t haystack_index = start; haystack_index + needle_len <= end; haystack_index++) {
if (memcmp(&haystack[haystack_index], needle, needle_len) == 0) {
for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) {
if (memcmp(haystack_ptr, needle, needle_len) == 0) {
num_occurrences++;
haystack_index += needle_len - 1;
haystack_ptr += needle_len;
} else {
haystack_ptr = utf8_next_char(haystack_ptr);
}
}

View File

@@ -40,8 +40,9 @@
#include <math.h>
#endif
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
const char *restrict top = str + len;
mp_obj_t mp_parse_num_integer(const char *restrict str_, uint len, int base) {
const byte *restrict str = (const byte *)str_;
const byte *restrict top = str + len;
bool neg = false;
mp_obj_t ret_val;
@@ -65,11 +66,11 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
}
// parse optional base prefix
str += mp_parse_num_base(str, top - str, &base);
str += mp_parse_num_base((const char*)str, top - str, &base);
// string should be an integer number
machine_int_t int_val = 0;
const char *restrict str_val_start = str;
const byte *restrict str_val_start = str;
for (; str < top; str++) {
// get next digit as a value
int dig = *str;
@@ -129,9 +130,9 @@ have_ret_val:
overflow:
// reparse using long int
{
const char *s2 = str_val_start;
const char *s2 = (const char*)str_val_start;
ret_val = mp_obj_new_int_from_str_len(&s2, top - str_val_start, neg, base);
str = s2;
str = (const byte*)s2;
goto have_ret_val;
}

View File

@@ -31,7 +31,7 @@
// find real radix base, and strip preceding '0x', '0o' and '0b'
// puts base in *base, and returns number of bytes to skip the prefix
int mp_parse_num_base(const char *str, uint len, int *base) {
const char *p = str;
const byte *p = (const byte*)str;
int c = *(p++);
if ((*base == 0 || *base == 16) && c == '0') {
c = *(p++);
@@ -63,6 +63,6 @@ int mp_parse_num_base(const char *str, uint len, int *base) {
}
p--;
}
return p - str;
return p - (const byte*)str;
}

View File

@@ -217,7 +217,7 @@ STATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) {
mp_obj_t lines = mp_obj_new_list(0, NULL);
for (;;) {
mp_obj_t line = stream_unbuffered_readline(1, &self);
if (mp_obj_str_get_len(line) == 0) {
if (!mp_obj_is_true(line)) {
break;
}
mp_obj_list_append(lines, line);
@@ -228,7 +228,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj, stream_unbuffered_
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
mp_obj_t l_in = stream_unbuffered_readline(1, &self);
if (mp_obj_str_get_len(l_in) != 0) {
if (mp_obj_is_true(l_in)) {
return l_in;
}
return MP_OBJ_STOP_ITERATION;

View File

@@ -65,12 +65,12 @@ STATIC const uint8_t attr[] = {
AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0
};
unichar utf8_get_char(const char *s) {
unichar utf8_get_char(const byte *s) {
return *s;
}
char *utf8_next_char(const char *s) {
return (char*)(s + 1);
const byte *utf8_next_char(const byte *s) {
return s + 1;
}
bool unichar_isspace(unichar c) {

View File

@@ -70,7 +70,7 @@ typedef struct _pyb_file_obj_t {
} pyb_file_obj_t;
void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
printf("<io.%s %p>", mp_obj_get_type_str(self_in), self_in);
print(env, "<io.%s %p>", mp_obj_get_type_str(self_in), self_in);
}
STATIC machine_int_t file_obj_read(mp_obj_t self_in, void *buf, machine_uint_t size, int *errcode) {

View File

@@ -39,376 +39,430 @@
#include "obj.h"
#include "runtime.h"
#include "systick.h"
#include "pin.h"
#include "genhdr/pins.h"
#include "bufhelper.h"
#include "spi.h"
#include "font_petme128_8x8.h"
#include "lcd.h"
#if defined(PYBV3)
#define PYB_LCD_PORT (GPIOA)
#define PYB_LCD_CS1_PIN (GPIO_PIN_0)
#define PYB_LCD_RST_PIN (GPIO_PIN_1)
#define PYB_LCD_A0_PIN (GPIO_PIN_2)
#define PYB_LCD_SCL_PIN (GPIO_PIN_3)
#define PYB_LCD_SI_PIN (GPIO_PIN_4)
#elif defined(PYBV4) || defined(PYBV10)
// X position
#define PYB_LCD_PORT (GPIOA)
#define PYB_LCD_CS1_PIN (GPIO_PIN_2) // X3
#define PYB_LCD_RST_PIN (GPIO_PIN_3) // X4
#define PYB_LCD_A0_PIN (GPIO_PIN_4) // X5
#define PYB_LCD_SCL_PIN (GPIO_PIN_5) // X6
#define PYB_LCD_SI_PIN (GPIO_PIN_7) // X8
#define PYB_LCD_BL_PORT (GPIOC)
#define PYB_LCD_BL_PIN (GPIO_PIN_5) // X12
/*
// Y position
#define PYB_LCD_PORT (GPIOB)
#define PYB_LCD_CS1_PIN (GPIO_PIN_8) // Y3 = PB8
#define PYB_LCD_RST_PIN (GPIO_PIN_9) // Y4 = PB9
#define PYB_LCD_A0_PIN (GPIO_PIN_12) // Y5 = PB12
#define PYB_LCD_SCL_PIN (GPIO_PIN_13) // Y6 = PB13
#define PYB_LCD_SI_PIN (GPIO_PIN_15) // Y8 = PB15
#define PYB_LCD_BL_PORT (GPIOB)
#define PYB_LCD_BL_PIN (GPIO_PIN_1) // Y12 = PB1
*/
#elif defined(STM32F4DISC)
/* Configure if needed */
#define PYB_LCD_PORT (GPIOA)
#define PYB_LCD_CS1_PIN (GPIO_PIN_2) // X3
#define PYB_LCD_RST_PIN (GPIO_PIN_3) // X4
#define PYB_LCD_A0_PIN (GPIO_PIN_4) // X5
#define PYB_LCD_SCL_PIN (GPIO_PIN_5) // X6
#define PYB_LCD_SI_PIN (GPIO_PIN_7) // X8
#define PYB_LCD_BL_PORT (GPIOC)
#define PYB_LCD_BL_PIN (GPIO_PIN_5) // X12
#endif
#define LCD_INSTR (0)
#define LCD_DATA (1)
static void lcd_delay(void) {
#define LCD_CHAR_BUF_W (16)
#define LCD_CHAR_BUF_H (4)
#define LCD_PIX_BUF_W (128)
#define LCD_PIX_BUF_H (32)
#define LCD_PIX_BUF_BYTE_SIZE (LCD_PIX_BUF_W * LCD_PIX_BUF_H / 8)
typedef struct _pyb_lcd_obj_t {
mp_obj_base_t base;
// hardware control for the LCD
SPI_HandleTypeDef *spi;
const pin_obj_t *pin_cs1;
const pin_obj_t *pin_rst;
const pin_obj_t *pin_a0;
const pin_obj_t *pin_bl;
// character buffer for stdout-like output
char char_buffer[LCD_CHAR_BUF_W * LCD_CHAR_BUF_H];
int line;
int column;
int next_line;
// double buffering for pixel buffer
byte pix_buf[LCD_PIX_BUF_BYTE_SIZE];
byte pix_buf2[LCD_PIX_BUF_BYTE_SIZE];
} pyb_lcd_obj_t;
STATIC void lcd_delay(void) {
__asm volatile ("nop\nnop");
}
static void lcd_out(int instr_data, uint8_t i) {
STATIC void lcd_out(pyb_lcd_obj_t *lcd, int instr_data, uint8_t i) {
lcd_delay();
PYB_LCD_PORT->BSRRH = PYB_LCD_CS1_PIN; // CS=0; enable
lcd->pin_cs1->gpio->BSRRH = lcd->pin_cs1->pin_mask; // CS=0; enable
if (instr_data == LCD_INSTR) {
PYB_LCD_PORT->BSRRH = PYB_LCD_A0_PIN; // A0=0; select instr reg
lcd->pin_a0->gpio->BSRRH = lcd->pin_a0->pin_mask; // A0=0; select instr reg
} else {
PYB_LCD_PORT->BSRRL = PYB_LCD_A0_PIN; // A0=1; select data reg
lcd->pin_a0->gpio->BSRRL = lcd->pin_a0->pin_mask; // A0=1; select data reg
}
// send byte bigendian, latches on rising clock
for (uint32_t n = 0; n < 8; n++) {
lcd_delay();
PYB_LCD_PORT->BSRRH = PYB_LCD_SCL_PIN; // SCL=0
if ((i & 0x80) == 0) {
PYB_LCD_PORT->BSRRH = PYB_LCD_SI_PIN; // SI=0
} else {
PYB_LCD_PORT->BSRRL = PYB_LCD_SI_PIN; // SI=1
}
i <<= 1;
lcd_delay();
PYB_LCD_PORT->BSRRL = PYB_LCD_SCL_PIN; // SCL=1
}
PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_PIN; // CS=1; disable
/*
in Python, native types:
CS1_PIN(const) = 0
n = int(0)
delay_ms(0)
PORT[word:BSRRH] = 1 << CS1_PIN
for n in range(0, 8):
delay_ms(0)
PORT[word:BSRRH] = 1 << SCL_PIN
if i & 0x80 == 0:
PORT[word:BSRRH] = 1 << SI_PIN
else:
PORT[word:BSRRL] = 1 << SI_PIN
i <<= 1
delay_ms(0)
PORT[word:BSRRL] = 1 << SCL_PIN
*/
lcd_delay();
HAL_SPI_Transmit(lcd->spi, &i, 1, 1000);
}
/*
static void lcd_data_out(uint8_t i) {
delay_ms(0);
PYB_LCD_PORT->BSRRH = PYB_LCD_CS1_PIN; // CS=0; enable
PYB_LCD_PORT->BSRRL = PYB_LCD_A0_PIN; // A0=1; select data reg
// send byte bigendian, latches on rising clock
for (uint32_t n = 0; n < 8; n++) {
delay_ms(0);
PYB_LCD_PORT->BSRRH = PYB_LCD_SCL_PIN; // SCL=0
if ((i & 0x80) == 0) {
PYB_LCD_PORT->BSRRH = PYB_LCD_SI_PIN; // SI=0
} else {
PYB_LCD_PORT->BSRRL = PYB_LCD_SI_PIN; // SI=1
}
i <<= 1;
delay_ms(0);
PYB_LCD_PORT->BSRRL = PYB_LCD_SCL_PIN; // SCL=1
}
PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_PIN; // CS=1; disable
}
*/
// writes 8 vertical pixels
// pos 0 is upper left, pos 1 is 8 pixels to right of that, pos 128 is 8 pixels below that
mp_obj_t lcd_draw_pixel_8(mp_obj_t mp_pos, mp_obj_t mp_val) {
int pos = mp_obj_get_int(mp_pos);
int val = mp_obj_get_int(mp_val);
int page = pos / 128;
int offset = pos - (page * 128);
lcd_out(LCD_INSTR, 0xb0 | page); // page address set
lcd_out(LCD_INSTR, 0x10 | ((offset >> 4) & 0x0f)); // column address set upper
lcd_out(LCD_INSTR, 0x00 | (offset & 0x0f)); // column address set lower
lcd_out(LCD_DATA, val); // write data
return mp_const_none;
}
#define LCD_BUF_W (16)
#define LCD_BUF_H (4)
char lcd_char_buffer[LCD_BUF_W * LCD_BUF_H];
int lcd_line;
int lcd_column;
int lcd_next_line;
#define LCD_PIX_BUF_SIZE (128 * 32 / 8)
byte lcd_pix_buf[LCD_PIX_BUF_SIZE];
byte lcd_pix_buf2[LCD_PIX_BUF_SIZE];
mp_obj_t lcd_pix_clear(void) {
memset(lcd_pix_buf, 0, LCD_PIX_BUF_SIZE);
memset(lcd_pix_buf2, 0, LCD_PIX_BUF_SIZE);
return mp_const_none;
}
mp_obj_t lcd_pix_get(mp_obj_t mp_x, mp_obj_t mp_y) {
int x = mp_obj_get_int(mp_x);
int y = mp_obj_get_int(mp_y);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
if (lcd_pix_buf[byte_pos] & (1 << (y & 7))) {
return mp_obj_new_int(1);
}
}
return mp_obj_new_int(0);
}
mp_obj_t lcd_pix_set(mp_obj_t mp_x, mp_obj_t mp_y) {
int x = mp_obj_get_int(mp_x);
int y = mp_obj_get_int(mp_y);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
lcd_pix_buf2[byte_pos] |= 1 << (y & 7);
}
return mp_const_none;
}
mp_obj_t lcd_pix_reset(mp_obj_t mp_x, mp_obj_t mp_y) {
int x = mp_obj_get_int(mp_x);
int y = mp_obj_get_int(mp_y);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
lcd_pix_buf2[byte_pos] &= ~(1 << (y & 7));
}
return mp_const_none;
}
mp_obj_t lcd_pix_show(void) {
memcpy(lcd_pix_buf, lcd_pix_buf2, LCD_PIX_BUF_SIZE);
for (uint page = 0; page < 4; page++) {
lcd_out(LCD_INSTR, 0xb0 | page); // page address set
lcd_out(LCD_INSTR, 0x10); // column address set upper; 0
lcd_out(LCD_INSTR, 0x00); // column address set lower; 0
for (uint i = 0; i < 128; i++) {
lcd_out(LCD_DATA, lcd_pix_buf[i + 128 * page]);
}
}
return mp_const_none;
}
mp_obj_t lcd_print(mp_obj_t text) {
uint len;
const char *data = mp_obj_str_get_data(text, &len);
lcd_print_strn(data, len);
return mp_const_none;
}
mp_obj_t lcd_light(mp_obj_t value) {
#if defined(PYB_LCD_BL_PORT)
if (mp_obj_is_true(value)) {
PYB_LCD_BL_PORT->BSRRL = PYB_LCD_BL_PIN; // set pin high to turn backlight on
} else {
PYB_LCD_BL_PORT->BSRRH = PYB_LCD_BL_PIN; // set pin low to turn backlight off
}
#endif
return mp_const_none;
}
static mp_obj_t mp_lcd = MP_OBJ_NULL;
static mp_obj_t pyb_lcd_init(void) {
if (mp_lcd != MP_OBJ_NULL) {
// already init'd
return mp_lcd;
}
// set the outputs high
PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_PIN;
PYB_LCD_PORT->BSRRL = PYB_LCD_RST_PIN;
PYB_LCD_PORT->BSRRL = PYB_LCD_A0_PIN;
PYB_LCD_PORT->BSRRL = PYB_LCD_SCL_PIN;
PYB_LCD_PORT->BSRRL = PYB_LCD_SI_PIN;
// make them push/pull outputs
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = PYB_LCD_CS1_PIN | PYB_LCD_RST_PIN | PYB_LCD_A0_PIN | PYB_LCD_SCL_PIN | PYB_LCD_SI_PIN;
HAL_GPIO_Init(PYB_LCD_PORT, &GPIO_InitStructure);
#if defined(PYB_LCD_BL_PORT)
// backlight drive pin, starts low (off)
PYB_LCD_BL_PORT->BSRRH = PYB_LCD_BL_PIN;
GPIO_InitStructure.Pin = PYB_LCD_BL_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(PYB_LCD_BL_PORT, &GPIO_InitStructure);
#endif
// init the LCD
HAL_Delay(1); // wait a bit
PYB_LCD_PORT->BSRRH = PYB_LCD_RST_PIN; // RST=0; reset
HAL_Delay(1); // wait for reset; 2us min
PYB_LCD_PORT->BSRRL = PYB_LCD_RST_PIN; // RST=1; enable
HAL_Delay(1); // wait for reset; 2us min
lcd_out(LCD_INSTR, 0xa0); // ADC select, normal
lcd_out(LCD_INSTR, 0xc8); // common output mode select, reverse
lcd_out(LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias
lcd_out(LCD_INSTR, 0x2f); // power control set, 0b111=(booster on, vreg on, vfollow on)
lcd_out(LCD_INSTR, 0x21); // v0 voltage regulator internal resistor ratio set, 0b001=small
lcd_out(LCD_INSTR, 0x81); // electronic volume mode set
lcd_out(LCD_INSTR, 0x34); // electronic volume register set, 0b110100
lcd_out(LCD_INSTR, 0x40); // display start line set, 0
lcd_out(LCD_INSTR, 0xaf); // LCD display, on
// clear display
for (int page = 0; page < 4; page++) {
lcd_out(LCD_INSTR, 0xb0 | page); // page address set
lcd_out(LCD_INSTR, 0x10); // column address set upper
lcd_out(LCD_INSTR, 0x00); // column address set lower
for (int i = 0; i < 128; i++) {
lcd_out(LCD_DATA, 0x00);
}
}
for (int i = 0; i < LCD_BUF_H * LCD_BUF_W; i++) {
lcd_char_buffer[i] = ' ';
}
lcd_line = 0;
lcd_column = 0;
lcd_next_line = 0;
// Micro Python interface
mp_obj_t o = mp_obj_new_type(MP_QSTR_LCD, mp_const_empty_tuple, mp_obj_new_dict(0));
mp_store_attr(o, qstr_from_str("lcd8"), mp_make_function_n(2, lcd_draw_pixel_8));
mp_store_attr(o, qstr_from_str("clear"), mp_make_function_n(0, lcd_pix_clear));
mp_store_attr(o, qstr_from_str("get"), mp_make_function_n(2, lcd_pix_get));
mp_store_attr(o, qstr_from_str("set"), mp_make_function_n(2, lcd_pix_set));
mp_store_attr(o, qstr_from_str("reset"), mp_make_function_n(2, lcd_pix_reset));
mp_store_attr(o, qstr_from_str("show"), mp_make_function_n(0, lcd_pix_show));
mp_store_attr(o, qstr_from_str("text"), mp_make_function_n(1, lcd_print));
mp_store_attr(o, qstr_from_str("light"), mp_make_function_n(1, lcd_light));
mp_lcd = o;
return o;
}
static MP_DEFINE_CONST_FUN_OBJ_0(pyb_lcd_init_obj, pyb_lcd_init);
void lcd_init(void) {
mp_lcd = MP_OBJ_NULL;
mp_store_name(qstr_from_str("LCD"), (mp_obj_t)&pyb_lcd_init_obj);
}
void lcd_print_str(const char *str) {
lcd_print_strn(str, strlen(str));
}
void lcd_print_strn(const char *str, unsigned int len) {
int redraw_min = lcd_line * LCD_BUF_W + lcd_column;
// write a string to the LCD at the current cursor location
// output it straight away (doesn't use the pixel buffer)
STATIC void lcd_write_strn(pyb_lcd_obj_t *lcd, const char *str, unsigned int len) {
int redraw_min = lcd->line * LCD_CHAR_BUF_W + lcd->column;
int redraw_max = redraw_min;
int did_new_line = 0;
for (; len > 0; len--, str++) {
// move to next line if needed
if (lcd_next_line) {
if (lcd_line + 1 < LCD_BUF_H) {
lcd_line += 1;
if (lcd->next_line) {
if (lcd->line + 1 < LCD_CHAR_BUF_H) {
lcd->line += 1;
} else {
lcd_line = LCD_BUF_H - 1;
for (int i = 0; i < LCD_BUF_W * (LCD_BUF_H - 1); i++) {
lcd_char_buffer[i] = lcd_char_buffer[i + LCD_BUF_W];
lcd->line = LCD_CHAR_BUF_H - 1;
for (int i = 0; i < LCD_CHAR_BUF_W * (LCD_CHAR_BUF_H - 1); i++) {
lcd->char_buffer[i] = lcd->char_buffer[i + LCD_CHAR_BUF_W];
}
for (int i = 0; i < LCD_BUF_W; i++) {
lcd_char_buffer[LCD_BUF_W * (LCD_BUF_H - 1) + i] = ' ';
for (int i = 0; i < LCD_CHAR_BUF_W; i++) {
lcd->char_buffer[LCD_CHAR_BUF_W * (LCD_CHAR_BUF_H - 1) + i] = ' ';
}
redraw_min = 0;
redraw_max = LCD_BUF_W * LCD_BUF_H;
redraw_max = LCD_CHAR_BUF_W * LCD_CHAR_BUF_H;
}
lcd_next_line = 0;
lcd_column = 0;
did_new_line = 1;
lcd->next_line = 0;
lcd->column = 0;
}
if (*str == '\n') {
lcd_next_line = 1;
lcd->next_line = 1;
} else if (*str == '\r') {
lcd_column = 0;
lcd->column = 0;
} else if (*str == '\b') {
if (lcd_column > 0) {
lcd_column--;
if (lcd->column > 0) {
lcd->column--;
redraw_min = 0; // could optimise this to not redraw everything
}
} else if (lcd_column >= LCD_BUF_W) {
lcd_next_line = 1;
} else if (lcd->column >= LCD_CHAR_BUF_W) {
lcd->next_line = 1;
str -= 1;
len += 1;
} else {
lcd_char_buffer[lcd_line * LCD_BUF_W + lcd_column] = *str;
lcd_column += 1;
int max = lcd_line * LCD_BUF_W + lcd_column;
lcd->char_buffer[lcd->line * LCD_CHAR_BUF_W + lcd->column] = *str;
lcd->column += 1;
int max = lcd->line * LCD_CHAR_BUF_W + lcd->column;
if (max > redraw_max) {
redraw_max = max;
}
}
}
int last_page = -1;
// we must draw upside down, because the LCD is upside down
for (int i = redraw_min; i < redraw_max; i++) {
int page = i / LCD_BUF_W;
if (page != last_page) {
int offset = 8 * (i - (page * LCD_BUF_W));
lcd_out(LCD_INSTR, 0xb0 | page); // page address set
lcd_out(LCD_INSTR, 0x10 | ((offset >> 4) & 0x0f)); // column address set upper
lcd_out(LCD_INSTR, 0x00 | (offset & 0x0f)); // column address set lower
last_page = page;
}
int chr = lcd_char_buffer[i];
uint page = i / LCD_CHAR_BUF_W;
uint offset = 8 * (LCD_CHAR_BUF_W - 1 - (i - (page * LCD_CHAR_BUF_W)));
lcd_out(lcd, LCD_INSTR, 0xb0 | page); // page address set
lcd_out(lcd, LCD_INSTR, 0x10 | ((offset >> 4) & 0x0f)); // column address set upper
lcd_out(lcd, LCD_INSTR, 0x00 | (offset & 0x0f)); // column address set lower
int chr = lcd->char_buffer[i];
if (chr < 32 || chr > 126) {
chr = 127;
}
const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8];
for (int j = 0; j < 8; j++) {
lcd_out(LCD_DATA, chr_data[j]);
for (int j = 7; j >= 0; j--) {
lcd_out(lcd, LCD_DATA, chr_data[j]);
}
}
if (did_new_line) {
HAL_Delay(50);
}
}
STATIC mp_obj_t pyb_lcd_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// get LCD position
const char *lcd_id = mp_obj_str_get_str(args[0]);
// create lcd object
pyb_lcd_obj_t *lcd = m_new_obj(pyb_lcd_obj_t);
lcd->base.type = &pyb_lcd_type;
// configure pins
// TODO accept an SPI object and pin objects for full customisation
if ((lcd_id[0] | 0x20) == 'x' && lcd_id[1] == '\0') {
lcd->spi = &SPIHandle1;
lcd->pin_cs1 = &pin_A2; // X3
lcd->pin_rst = &pin_A3; // X4
lcd->pin_a0 = &pin_A4; // X5
lcd->pin_bl = &pin_C5; // X12
} else if ((lcd_id[0] | 0x20) == 'y' && lcd_id[1] == '\0') {
lcd->spi = &SPIHandle2;
lcd->pin_cs1 = &pin_B8; // Y3
lcd->pin_rst = &pin_B9; // Y4
lcd->pin_a0 = &pin_B12; // Y5
lcd->pin_bl = &pin_B1; // Y12
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LCD bus '%s' does not exist", lcd_id));
}
// init the SPI bus
SPI_InitTypeDef *init = &lcd->spi->Init;
init->Mode = SPI_MODE_MASTER;
// compute the baudrate prescaler from the desired baudrate
// select a prescaler that yields at most the desired baudrate
uint spi_clock;
if (lcd->spi->Instance == SPI1) {
// SPI1 is on APB2
spi_clock = HAL_RCC_GetPCLK2Freq();
} else {
// SPI2 and SPI3 are on APB1
spi_clock = HAL_RCC_GetPCLK1Freq();
}
uint br_prescale = spi_clock / 16000000; // datasheet says LCD can run at 20MHz, but we go for 16MHz
if (br_prescale <= 2) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; }
else if (br_prescale <= 4) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; }
else if (br_prescale <= 8) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; }
else if (br_prescale <= 16) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; }
else if (br_prescale <= 32) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; }
else if (br_prescale <= 64) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; }
else if (br_prescale <= 128) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; }
else { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; }
// data is sent bigendian, latches on rising clock
init->CLKPolarity = SPI_POLARITY_HIGH;
init->CLKPhase = SPI_PHASE_2EDGE;
init->Direction = SPI_DIRECTION_2LINES;
init->DataSize = SPI_DATASIZE_8BIT;
init->NSS = SPI_NSS_SOFT;
init->FirstBit = SPI_FIRSTBIT_MSB;
init->TIMode = SPI_TIMODE_DISABLED;
init->CRCCalculation = SPI_CRCCALCULATION_DISABLED;
init->CRCPolynomial = 0;
// init the SPI bus
spi_init(lcd->spi);
// set the pins to default values
lcd->pin_cs1->gpio->BSRRL = lcd->pin_cs1->pin_mask;
lcd->pin_rst->gpio->BSRRL = lcd->pin_rst->pin_mask;
lcd->pin_a0->gpio->BSRRL = lcd->pin_a0->pin_mask;
lcd->pin_bl->gpio->BSRRH = lcd->pin_bl->pin_mask;
// init the pins to be push/pull outputs
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = lcd->pin_cs1->pin_mask;
HAL_GPIO_Init(lcd->pin_cs1->gpio, &GPIO_InitStructure);
GPIO_InitStructure.Pin = lcd->pin_rst->pin_mask;
HAL_GPIO_Init(lcd->pin_rst->gpio, &GPIO_InitStructure);
GPIO_InitStructure.Pin = lcd->pin_a0->pin_mask;
HAL_GPIO_Init(lcd->pin_a0->gpio, &GPIO_InitStructure);
GPIO_InitStructure.Pin = lcd->pin_bl->pin_mask;
HAL_GPIO_Init(lcd->pin_bl->gpio, &GPIO_InitStructure);
// init the LCD
HAL_Delay(1); // wait a bit
lcd->pin_rst->gpio->BSRRH = lcd->pin_rst->pin_mask; // RST=0; reset
HAL_Delay(1); // wait for reset; 2us min
lcd->pin_rst->gpio->BSRRL = lcd->pin_rst->pin_mask; // RST=1; enable
HAL_Delay(1); // wait for reset; 2us min
lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal
lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display)
lcd_out(lcd, LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias
lcd_out(lcd, LCD_INSTR, 0x2f); // power control set, 0b111=(booster on, vreg on, vfollow on)
lcd_out(lcd, LCD_INSTR, 0x21); // v0 voltage regulator internal resistor ratio set, 0b001=small
lcd_out(lcd, LCD_INSTR, 0x81); // electronic volume mode set
lcd_out(lcd, LCD_INSTR, 0x28); // electronic volume register set
lcd_out(lcd, LCD_INSTR, 0x40); // display start line set, 0
lcd_out(lcd, LCD_INSTR, 0xaf); // LCD display, on
// clear LCD RAM
for (int page = 0; page < 4; page++) {
lcd_out(lcd, LCD_INSTR, 0xb0 | page); // page address set
lcd_out(lcd, LCD_INSTR, 0x10); // column address set upper
lcd_out(lcd, LCD_INSTR, 0x00); // column address set lower
for (int i = 0; i < 128; i++) {
lcd_out(lcd, LCD_DATA, 0x00);
}
}
// clear local char buffer
memset(lcd->char_buffer, ' ', LCD_CHAR_BUF_H * LCD_CHAR_BUF_W);
lcd->line = 0;
lcd->column = 0;
lcd->next_line = 0;
// clear local pixel buffer
memset(lcd->pix_buf, 0, LCD_PIX_BUF_BYTE_SIZE);
memset(lcd->pix_buf2, 0, LCD_PIX_BUF_BYTE_SIZE);
return lcd;
}
STATIC mp_obj_t pyb_lcd_command(mp_obj_t self_in, mp_obj_t instr_data_in, mp_obj_t val) {
pyb_lcd_obj_t *self = self_in;
// get whether instr or data
int instr_data = mp_obj_get_int(instr_data_in);
// get the buffer to send from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(val, &bufinfo, data);
// send the data
for (uint i = 0; i < bufinfo.len; i++) {
lcd_out(self, instr_data, ((byte*)bufinfo.buf)[i]);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_lcd_command_obj, pyb_lcd_command);
STATIC mp_obj_t pyb_lcd_contrast(mp_obj_t self_in, mp_obj_t contrast_in) {
pyb_lcd_obj_t *self = self_in;
int contrast = mp_obj_get_int(contrast_in);
if (contrast < 0) {
contrast = 0;
} else if (contrast > 0x2f) {
contrast = 0x2f;
}
lcd_out(self, LCD_INSTR, 0x81); // electronic volume mode set
lcd_out(self, LCD_INSTR, contrast); // electronic volume register set
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_contrast_obj, pyb_lcd_contrast);
STATIC mp_obj_t pyb_lcd_light(mp_obj_t self_in, mp_obj_t value) {
pyb_lcd_obj_t *self = self_in;
if (mp_obj_is_true(value)) {
self->pin_bl->gpio->BSRRL = self->pin_bl->pin_mask; // set pin high to turn backlight on
} else {
self->pin_bl->gpio->BSRRH = self->pin_bl->pin_mask; // set pin low to turn backlight off
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_light_obj, pyb_lcd_light);
STATIC mp_obj_t pyb_lcd_write(mp_obj_t self_in, mp_obj_t str) {
pyb_lcd_obj_t *self = self_in;
uint len;
const char *data = mp_obj_str_get_data(str, &len);
lcd_write_strn(self, data, len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_write_obj, pyb_lcd_write);
STATIC mp_obj_t pyb_lcd_fill(mp_obj_t self_in, mp_obj_t col_in) {
pyb_lcd_obj_t *self = self_in;
int col = mp_obj_get_int(col_in);
if (col) {
col = 0xff;
}
memset(self->pix_buf, col, LCD_PIX_BUF_BYTE_SIZE);
memset(self->pix_buf2, col, LCD_PIX_BUF_BYTE_SIZE);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_fill_obj, pyb_lcd_fill);
STATIC mp_obj_t pyb_lcd_get(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
pyb_lcd_obj_t *self = self_in;
int x = mp_obj_get_int(x_in);
int y = mp_obj_get_int(y_in);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
if (self->pix_buf[byte_pos] & (1 << (y & 7))) {
return mp_obj_new_int(1);
}
}
return mp_obj_new_int(0);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_lcd_get_obj, pyb_lcd_get);
STATIC mp_obj_t pyb_lcd_pixel(uint n_args, const mp_obj_t *args) {
pyb_lcd_obj_t *self = args[0];
int x = mp_obj_get_int(args[1]);
int y = mp_obj_get_int(args[2]);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
if (mp_obj_get_int(args[3]) == 0) {
self->pix_buf2[byte_pos] &= ~(1 << (y & 7));
} else {
self->pix_buf2[byte_pos] |= 1 << (y & 7);
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_lcd_pixel_obj, 4, 4, pyb_lcd_pixel);
STATIC mp_obj_t pyb_lcd_text(uint n_args, const mp_obj_t *args) {
// extract arguments
pyb_lcd_obj_t *self = args[0];
uint len;
const char *data = mp_obj_str_get_data(args[1], &len);
int x0 = mp_obj_get_int(args[2]);
int y0 = mp_obj_get_int(args[3]);
int col = mp_obj_get_int(args[4]);
// loop over chars
for (const char *top = data + len; data < top; data++) {
// get char and make sure its in range of font
uint chr = *(byte*)data;
if (chr < 32 || chr > 127) {
chr = 127;
}
// get char data
const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8];
// loop over char data
for (uint j = 0; j < 8; j++, x0++) {
if (0 <= x0 && x0 < LCD_PIX_BUF_W) { // clip x
uint vline_data = chr_data[j]; // each byte of char data is a vertical column of 8 pixels, LSB at top
for (int y = y0; vline_data; vline_data >>= 1, y++) { // scan over vertical column
if (vline_data & 1) { // only draw if pixel set
if (0 <= y && y < LCD_PIX_BUF_H) { // clip y
uint byte_pos = x0 + LCD_PIX_BUF_W * ((uint)y >> 3);
if (col == 0) {
// clear pixel
self->pix_buf2[byte_pos] &= ~(1 << (y & 7));
} else {
// set pixel
self->pix_buf2[byte_pos] |= 1 << (y & 7);
}
}
}
}
}
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_lcd_text_obj, 5, 5, pyb_lcd_text);
STATIC mp_obj_t pyb_lcd_show(mp_obj_t self_in) {
pyb_lcd_obj_t *self = self_in;
memcpy(self->pix_buf, self->pix_buf2, LCD_PIX_BUF_BYTE_SIZE);
for (uint page = 0; page < 4; page++) {
lcd_out(self, LCD_INSTR, 0xb0 | page); // page address set
lcd_out(self, LCD_INSTR, 0x10); // column address set upper; 0
lcd_out(self, LCD_INSTR, 0x00); // column address set lower; 0
for (uint i = 0; i < 128; i++) {
lcd_out(self, LCD_DATA, self->pix_buf[128 * page + 127 - i]);
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_lcd_show_obj, pyb_lcd_show);
STATIC const mp_map_elem_t pyb_lcd_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_command), (mp_obj_t)&pyb_lcd_command_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_contrast), (mp_obj_t)&pyb_lcd_contrast_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_light), (mp_obj_t)&pyb_lcd_light_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_lcd_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_fill), (mp_obj_t)&pyb_lcd_fill_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&pyb_lcd_get_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), (mp_obj_t)&pyb_lcd_pixel_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_text), (mp_obj_t)&pyb_lcd_text_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_show), (mp_obj_t)&pyb_lcd_show_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_lcd_locals_dict, pyb_lcd_locals_dict_table);
const mp_obj_type_t pyb_lcd_type = {
{ &mp_type_type },
.name = MP_QSTR_LCD,
.make_new = pyb_lcd_make_new,
.locals_dict = (mp_obj_t)&pyb_lcd_locals_dict,
};
#endif // MICROPY_HW_HAS_LCD

View File

@@ -24,6 +24,4 @@
* THE SOFTWARE.
*/
void lcd_init(void);
void lcd_print_str(const char *str);
void lcd_print_strn(const char *str, unsigned int len);
extern const mp_obj_type_t pyb_lcd_type;

View File

@@ -58,7 +58,6 @@
#include "storage.h"
#include "sdcard.h"
#include "ff.h"
#include "lcd.h"
#include "rng.h"
#include "accel.h"
#include "servo.h"
@@ -95,10 +94,6 @@ void __fatal_error(const char *msg) {
led_state(4, 1);
stdout_tx_strn("\nFATAL ERROR:\n", 14);
stdout_tx_strn(msg, strlen(msg));
#if 0 && MICROPY_HW_HAS_LCD
lcd_print_strn("\nFATAL ERROR:\n", 14);
lcd_print_strn(msg, strlen(msg));
#endif
for (uint i = 0;;) {
led_toggle(((i++) & 3) + 1);
for (volatile uint delay = 0; delay < 10000000; delay++) {
@@ -115,6 +110,15 @@ void nlr_jump_fail(void *val) {
__fatal_error("");
}
#ifndef NDEBUG
void __attribute__((weak))
__assert_func(const char *file, int line, const char *func, const char *expr) {
(void)func;
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
__fatal_error("");
}
#endif
STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL;
@@ -324,11 +328,6 @@ soft_reset:
pin_init();
extint_init();
#if MICROPY_HW_HAS_LCD
// LCD init (just creates class, init hardware by calling LCD())
lcd_init();
#endif
// local filesystem init
{
// try to mount the flash

View File

@@ -29,8 +29,9 @@
#include "stm32f4xx_hal.h"
#include "misc.h"
#include "mpconfig.h"
#include "misc.h"
#include "nlr.h"
#include "qstr.h"
#include "obj.h"
#include "gc.h"
@@ -54,6 +55,7 @@
#include "accel.h"
#include "servo.h"
#include "dac.h"
#include "lcd.h"
#include "usb.h"
#include "ff.h"
#include "portmodules.h"
@@ -301,6 +303,28 @@ STATIC mp_obj_t pyb_have_cdc(void ) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
/// \function repl_uart(uart)
/// Get or set the UART object that the REPL is repeated on.
STATIC mp_obj_t pyb_repl_uart(uint n_args, const mp_obj_t *args) {
if (n_args == 0) {
if (pyb_uart_global_debug == NULL) {
return mp_const_none;
} else {
return pyb_uart_global_debug;
}
} else {
if (args[0] == mp_const_none) {
pyb_uart_global_debug = NULL;
} else if (mp_obj_get_type(args[0]) == &pyb_uart_type) {
pyb_uart_global_debug = args[0];
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "need a UART object"));
}
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
/// \function hid((buttons, x, y, z))
/// Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
/// signal a HID mouse-motion event.
@@ -341,6 +365,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_have_cdc), (mp_obj_t)&pyb_have_cdc_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&pyb_repl_uart_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
@@ -390,6 +415,10 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
#if MICROPY_HW_HAS_MMA7660
{ MP_OBJ_NEW_QSTR(MP_QSTR_Accel), (mp_obj_t)&pyb_accel_type },
#endif
#if MICROPY_HW_HAS_LCD
{ MP_OBJ_NEW_QSTR(MP_QSTR_LCD), (mp_obj_t)&pyb_lcd_type },
#endif
};
STATIC const mp_obj_dict_t pyb_module_globals = {

View File

@@ -195,24 +195,14 @@ int pfenv_printf(const pfenv_t *pfenv, const char *fmt, va_list args) {
return chrs;
}
void stdout_print_strn(void *data, const char *str, unsigned int len) {
// send stdout to UART, USB CDC VCP, and LCD if nothing else
bool any = false;
STATIC void stdout_print_strn(void *data, const char *str, unsigned int len) {
// TODO this needs to be replaced with a proper stdio interface ala CPython
// send stdout to UART and USB CDC VCP
if (pyb_uart_global_debug != PYB_UART_NONE) {
uart_tx_strn_cooked(pyb_uart_global_debug, str, len);
any = true;
}
if (usb_vcp_is_enabled()) {
usb_vcp_send_strn_cooked(str, len);
any = true;
}
if (!any) {
#if 0
#if MICROPY_HW_HAS_LCD
lcd_print_strn(str, len);
#endif
#endif
}
}

View File

@@ -38,11 +38,14 @@
#include "usb.h"
#include "uart.h"
// TODO make stdin, stdout and stderr writable objects so they can
// be changed by Python code.
void stdout_tx_str(const char *str) {
if (pyb_uart_global_debug != PYB_UART_NONE) {
uart_tx_str(pyb_uart_global_debug, str);
}
#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
#if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
lcd_print_str(str);
#endif
usb_vcp_send_str(str);
@@ -52,7 +55,7 @@ void stdout_tx_strn(const char *str, uint len) {
if (pyb_uart_global_debug != PYB_UART_NONE) {
uart_tx_strn(pyb_uart_global_debug, str, len);
}
#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
#if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
lcd_print_strn(str, len);
#endif
usb_vcp_send_strn(str, len);
@@ -93,7 +96,7 @@ typedef struct _pyb_stdio_obj_t {
void stdio_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_stdio_obj_t *self = self_in;
printf("<io.FileIO %d>", self->fd);
print(env, "<io.FileIO %d>", self->fd);
}
STATIC machine_int_t stdio_read(mp_obj_t self_in, void *buf, machine_uint_t size, int *errcode) {

View File

@@ -54,10 +54,10 @@ Q(readall)
Q(readline)
Q(write)
Q(have_cdc)
Q(repl_uart)
Q(hid)
Q(time)
Q(rng)
Q(LCD)
Q(SD)
Q(SDcard)
Q(FileIO)
@@ -247,6 +247,17 @@ Q(sleep)
// for input
Q(input)
// for LCD class
Q(LCD)
Q(command)
Q(contrast)
Q(light)
Q(fill)
Q(get)
Q(pixel)
Q(text)
Q(show)
// for stm module
Q(stm)
Q(mem)

View File

@@ -199,7 +199,6 @@ void USR_KEYBRD_ProcessData(uint8_t pbuf) {
led_state(4, 1);
USB_OTG_BSP_mDelay(50);
led_state(4, 0);
//lcd_print_strn((char*)&pbuf, 1);
usb_keyboard_key = pbuf;
}

View File

@@ -1,3 +1,4 @@
# anything above 0xa0 is printed as Unicode by CPython
for c in range(0xa1):
# the abobe is CPython implementation detail, stick to ASCII
for c in range(0x80):
print("0x%02x: %s" % (c, repr(chr(c))))