nrf/boards/microbit: Add copy of microbit display and image files.

From micro:bit port repository, https://github.com/bbcmicrobit/micropython
This commit is contained in:
Glenn Ruben Bakke 2017-10-11 23:31:34 +02:00 committed by Damien George
parent a248db6916
commit 7a2e136049
12 changed files with 2817 additions and 0 deletions

View File

@ -0,0 +1,9 @@
Damien P. George (@dpgeorge)
Nicholas H. Tollervey (@ntoll)
Matthew Else (@matthewelse)
Alan M. Jackson (@alanmjackson)
Mark Shannon (@markshannon)
Larry Hastings (@larryhastings)
Mariia Koroliuk (@marichkakorolyuk)
Andrew Mulholland (@gbaman)
Joe Glancy (@JoeGlancy)

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2013-2016 The MicroPython-on-micro:bit Developers, as listed
in the accompanying AUTHORS file
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,70 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015/6 Mark Shannon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "lib/iters.h"
typedef struct _repeat_iterator_t {
mp_obj_base_t base;
mp_obj_t iterable;
mp_int_t index;
} repeat_iterator_t;
static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) {
repeat_iterator_t *iter = (repeat_iterator_t *)iter_in;
iter->index++;
if (iter->index >= mp_obj_get_int(mp_obj_len(iter->iterable))) {
iter->index = 0;
}
return mp_obj_subscr(iter->iterable, MP_OBJ_NEW_SMALL_INT(iter->index), MP_OBJ_SENTINEL);
}
const mp_obj_type_t microbit_repeat_iterator_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.print = NULL,
.make_new = NULL,
.call = NULL,
.unary_op = NULL,
.binary_op = NULL,
.attr = NULL,
.subscr = NULL,
.getiter = mp_identity,
.iternext = microbit_repeat_iter_next,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = MP_OBJ_NULL,
MP_OBJ_NULL
};
mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) {
repeat_iterator_t *result = m_new_obj(repeat_iterator_t);
result->base.type = &microbit_repeat_iterator_type;
result->iterable = iterable;
result->index = -1;
return result;
}

View File

@ -0,0 +1,4 @@
#include "py/runtime.h"
mp_obj_t microbit_repeat_iterator(mp_obj_t iterable);

View File

@ -0,0 +1,562 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "microbitobj.h"
extern "C" {
#include "py/runtime.h"
#include "modmicrobit.h"
#include "microbitimage.h"
#define IMAGE_T const monochrome_5by5_t
IMAGE_T microbit_const_image_heart_obj = SMALL_IMAGE(
0,1,0,1,0,
1,1,1,1,1,
1,1,1,1,1,
0,1,1,1,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_heart_small_obj = SMALL_IMAGE(
0,0,0,0,0,
0,1,0,1,0,
0,1,1,1,0,
0,0,1,0,0,
0,0,0,0,0
);
// smilies
IMAGE_T microbit_const_image_happy_obj = SMALL_IMAGE(
0,0,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
1,0,0,0,1,
0,1,1,1,0
);
IMAGE_T microbit_const_image_smile_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
1,0,0,0,1,
0,1,1,1,0
);
IMAGE_T microbit_const_image_sad_obj = SMALL_IMAGE(
0,0,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
0,1,1,1,0,
1,0,0,0,1
);
IMAGE_T microbit_const_image_confused_obj = SMALL_IMAGE(
0,0,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
0,1,0,1,0,
1,0,1,0,1
);
IMAGE_T microbit_const_image_angry_obj = SMALL_IMAGE(
1,0,0,0,1,
0,1,0,1,0,
0,0,0,0,0,
1,1,1,1,1,
1,0,1,0,1
);
IMAGE_T microbit_const_image_asleep_obj = SMALL_IMAGE(
0,0,0,0,0,
1,1,0,1,1,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_surprised_obj = SMALL_IMAGE(
0,1,0,1,0,
0,0,0,0,0,
0,0,1,0,0,
0,1,0,1,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_silly_obj = SMALL_IMAGE(
1,0,0,0,1,
0,0,0,0,0,
1,1,1,1,1,
0,0,1,0,1,
0,0,1,1,1
);
IMAGE_T microbit_const_image_fabulous_obj = SMALL_IMAGE(
1,1,1,1,1,
1,1,0,1,1,
0,0,0,0,0,
0,1,0,1,0,
0,1,1,1,0
);
IMAGE_T microbit_const_image_meh_obj = SMALL_IMAGE(
0,1,0,1,0,
0,0,0,0,0,
0,0,0,1,0,
0,0,1,0,0,
0,1,0,0,0
);
// yes/no
IMAGE_T microbit_const_image_yes_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,1,
0,0,0,1,0,
1,0,1,0,0,
0,1,0,0,0
);
IMAGE_T microbit_const_image_no_obj = SMALL_IMAGE(
1,0,0,0,1,
0,1,0,1,0,
0,0,1,0,0,
0,1,0,1,0,
1,0,0,0,1
);
// clock hands
IMAGE_T microbit_const_image_clock12_obj = SMALL_IMAGE(
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock1_obj = SMALL_IMAGE(
0,0,0,1,0,
0,0,0,1,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock2_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,1,1,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock3_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,1,1,1,
0,0,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock4_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0,
0,0,0,1,1,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock5_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0,
0,0,0,1,0,
0,0,0,1,0
);
IMAGE_T microbit_const_image_clock6_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_clock7_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0,
0,1,0,0,0,
0,1,0,0,0
);
IMAGE_T microbit_const_image_clock8_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0,
1,1,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock9_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,0,0,0,
1,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock10_obj = SMALL_IMAGE(
0,0,0,0,0,
1,1,0,0,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_clock11_obj = SMALL_IMAGE(
0,1,0,0,0,
0,1,0,0,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0
);
// arrows
IMAGE_T microbit_const_image_arrow_n_obj = SMALL_IMAGE(
0,0,1,0,0,
0,1,1,1,0,
1,0,1,0,1,
0,0,1,0,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_arrow_ne_obj = SMALL_IMAGE(
0,0,1,1,1,
0,0,0,1,1,
0,0,1,0,1,
0,1,0,0,0,
1,0,0,0,0
);
IMAGE_T microbit_const_image_arrow_e_obj = SMALL_IMAGE(
0,0,1,0,0,
0,0,0,1,0,
1,1,1,1,1,
0,0,0,1,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_arrow_se_obj = SMALL_IMAGE(
1,0,0,0,0,
0,1,0,0,0,
0,0,1,0,1,
0,0,0,1,1,
0,0,1,1,1
);
IMAGE_T microbit_const_image_arrow_s_obj = SMALL_IMAGE(
0,0,1,0,0,
0,0,1,0,0,
1,0,1,0,1,
0,1,1,1,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_arrow_sw_obj = SMALL_IMAGE(
0,0,0,0,1,
0,0,0,1,0,
1,0,1,0,0,
1,1,0,0,0,
1,1,1,0,0
);
IMAGE_T microbit_const_image_arrow_w_obj = SMALL_IMAGE(
0,0,1,0,0,
0,1,0,0,0,
1,1,1,1,1,
0,1,0,0,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_arrow_nw_obj = SMALL_IMAGE(
1,1,1,0,0,
1,1,0,0,0,
1,0,1,0,0,
0,0,0,1,0,
0,0,0,0,1
);
// geometry
IMAGE_T microbit_const_image_triangle_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,1,0,0,
0,1,0,1,0,
1,1,1,1,1,
0,0,0,0,0
);
IMAGE_T microbit_const_image_triangle_left_obj = SMALL_IMAGE(
1,0,0,0,0,
1,1,0,0,0,
1,0,1,0,0,
1,0,0,1,0,
1,1,1,1,1
);
IMAGE_T microbit_const_image_chessboard_obj = SMALL_IMAGE(
0,1,0,1,0,
1,0,1,0,1,
0,1,0,1,0,
1,0,1,0,1,
0,1,0,1,0
);
IMAGE_T microbit_const_image_diamond_obj = SMALL_IMAGE(
0,0,1,0,0,
0,1,0,1,0,
1,0,0,0,1,
0,1,0,1,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_diamond_small_obj = SMALL_IMAGE(
0,0,0,0,0,
0,0,1,0,0,
0,1,0,1,0,
0,0,1,0,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_square_obj = SMALL_IMAGE(
1,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,1
);
IMAGE_T microbit_const_image_square_small_obj = SMALL_IMAGE(
0,0,0,0,0,
0,1,1,1,0,
0,1,0,1,0,
0,1,1,1,0,
0,0,0,0,0
);
// animals
IMAGE_T microbit_const_image_rabbit = SMALL_IMAGE(
1,0,1,0,0,
1,0,1,0,0,
1,1,1,1,0,
1,1,0,1,0,
1,1,1,1,0
);
IMAGE_T microbit_const_image_cow = SMALL_IMAGE(
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,1,
0,1,1,1,0,
0,0,1,0,0
);
// musical notes
IMAGE_T microbit_const_image_music_crotchet_obj = SMALL_IMAGE(
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
1,1,1,0,0,
1,1,1,0,0
);
IMAGE_T microbit_const_image_music_quaver_obj = SMALL_IMAGE(
0,0,1,0,0,
0,0,1,1,0,
0,0,1,0,1,
1,1,1,0,0,
1,1,1,0,0
);
IMAGE_T microbit_const_image_music_quavers_obj = SMALL_IMAGE(
0,1,1,1,1,
0,1,0,0,1,
0,1,0,0,1,
1,1,0,1,1,
1,1,0,1,1
);
// other icons
IMAGE_T microbit_const_image_pitchfork_obj = SMALL_IMAGE(
1,0,1,0,1,
1,0,1,0,1,
1,1,1,1,1,
0,0,1,0,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_xmas_obj = SMALL_IMAGE(
0,0,1,0,0,
0,1,1,1,0,
0,0,1,0,0,
0,1,1,1,0,
1,1,1,1,1
);
IMAGE_T microbit_const_image_pacman_obj = SMALL_IMAGE(
0,1,1,1,1,
1,1,0,1,0,
1,1,1,0,0,
1,1,1,1,0,
0,1,1,1,1
);
IMAGE_T microbit_const_image_target_obj = SMALL_IMAGE(
0,0,1,0,0,
0,1,1,1,0,
1,1,0,1,1,
0,1,1,1,0,
0,0,1,0,0
);
/*
The following images were designed by Abbie Brooks.
*/
IMAGE_T microbit_const_image_tshirt_obj = SMALL_IMAGE(
1,1,0,1,1,
1,1,1,1,1,
0,1,1,1,0,
0,1,1,1,0,
0,1,1,1,0
);
IMAGE_T microbit_const_image_rollerskate_obj = SMALL_IMAGE(
0,0,0,1,1,
0,0,0,1,1,
1,1,1,1,1,
1,1,1,1,1,
0,1,0,1,0
);
IMAGE_T microbit_const_image_duck_obj = SMALL_IMAGE(
0,1,1,0,0,
1,1,1,0,0,
0,1,1,1,1,
0,1,1,1,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_house_obj = SMALL_IMAGE(
0,0,1,0,0,
0,1,1,1,0,
1,1,1,1,1,
0,1,1,1,0,
0,1,0,1,0
);
IMAGE_T microbit_const_image_tortoise_obj = SMALL_IMAGE(
0,0,0,0,0,
0,1,1,1,0,
1,1,1,1,1,
0,1,0,1,0,
0,0,0,0,0
);
IMAGE_T microbit_const_image_butterfly_obj = SMALL_IMAGE(
1,1,0,1,1,
1,1,1,1,1,
0,0,1,0,0,
1,1,1,1,1,
1,1,0,1,1
);
IMAGE_T microbit_const_image_stickfigure_obj = SMALL_IMAGE(
0,0,1,0,0,
1,1,1,1,1,
0,0,1,0,0,
0,1,0,1,0,
1,0,0,0,1
);
IMAGE_T microbit_const_image_ghost_obj = SMALL_IMAGE(
1,1,1,1,1,
1,0,1,0,1,
1,1,1,1,1,
1,1,1,1,1,
1,0,1,0,1
);
IMAGE_T microbit_const_image_sword_obj = SMALL_IMAGE(
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,1,1,1,0,
0,0,1,0,0
);
IMAGE_T microbit_const_image_giraffe_obj = SMALL_IMAGE(
1,1,0,0,0,
0,1,0,0,0,
0,1,0,0,0,
0,1,1,1,0,
0,1,0,1,0
);
IMAGE_T microbit_const_image_skull_obj = SMALL_IMAGE(
0,1,1,1,0,
1,0,1,0,1,
1,1,1,1,1,
0,1,1,1,0,
0,1,1,1,0
);
IMAGE_T microbit_const_image_umbrella_obj = SMALL_IMAGE(
0,1,1,1,0,
1,1,1,1,1,
0,0,1,0,0,
1,0,1,0,0,
0,1,1,0,0
);
IMAGE_T microbit_const_image_snake_obj = SMALL_IMAGE(
1,1,0,0,0,
1,1,0,1,1,
0,1,0,1,0,
0,1,1,1,0,
0,0,0,0,0
);
}

View File

@ -0,0 +1,60 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Mark Shannon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "modmicrobit.h"
const mp_obj_tuple_t microbit_const_image_all_clocks_tuple_obj = {
{&mp_type_tuple},
.len = 12,
.items = {
(mp_obj_t)&microbit_const_image_clock12_obj,
(mp_obj_t)&microbit_const_image_clock1_obj,
(mp_obj_t)&microbit_const_image_clock2_obj,
(mp_obj_t)&microbit_const_image_clock3_obj,
(mp_obj_t)&microbit_const_image_clock4_obj,
(mp_obj_t)&microbit_const_image_clock5_obj,
(mp_obj_t)&microbit_const_image_clock6_obj,
(mp_obj_t)&microbit_const_image_clock7_obj,
(mp_obj_t)&microbit_const_image_clock8_obj,
(mp_obj_t)&microbit_const_image_clock9_obj,
(mp_obj_t)&microbit_const_image_clock10_obj,
(mp_obj_t)&microbit_const_image_clock11_obj
}
};
const mp_obj_tuple_t microbit_const_image_all_arrows_tuple_obj = {
{&mp_type_tuple},
.len = 8,
.items = {
(mp_obj_t)&microbit_const_image_arrow_n_obj,
(mp_obj_t)&microbit_const_image_arrow_ne_obj,
(mp_obj_t)&microbit_const_image_arrow_e_obj,
(mp_obj_t)&microbit_const_image_arrow_se_obj,
(mp_obj_t)&microbit_const_image_arrow_s_obj,
(mp_obj_t)&microbit_const_image_arrow_sw_obj,
(mp_obj_t)&microbit_const_image_arrow_w_obj,
(mp_obj_t)&microbit_const_image_arrow_nw_obj
}
};

View File

@ -0,0 +1,579 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "microbitobj.h"
#include "nrf_gpio.h"
extern "C" {
#include "py/runtime.h"
#include "py/gc.h"
#include "modmicrobit.h"
#include "microbitimage.h"
#include "microbitdisplay.h"
#include "microbitpin.h"
#include "lib/iters.h"
#include "lib/ticker.h"
#define min(a,b) (((a)<(b))?(a):(b))
void microbit_display_show(microbit_display_obj_t *display, microbit_image_obj_t *image) {
mp_int_t w = min(image->width(), 5);
mp_int_t h = min(image->height(), 5);
mp_int_t x = 0;
mp_int_t brightnesses = 0;
for (; x < w; ++x) {
mp_int_t y = 0;
for (; y < h; ++y) {
uint8_t pix = image->getPixelValue(x, y);
display->image_buffer[x][y] = pix;
brightnesses |= (1 << pix);
}
for (; y < 5; ++y) {
display->image_buffer[x][y] = 0;
}
}
for (; x < 5; ++x) {
for (mp_int_t y = 0; y < 5; ++y) {
display->image_buffer[x][y] = 0;
}
}
display->brightnesses = brightnesses;
}
#define DEFAULT_PRINT_SPEED 400
mp_obj_t microbit_display_show_func(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// Cancel any animations.
MP_STATE_PORT(async_data)[0] = NULL;
MP_STATE_PORT(async_data)[1] = NULL;
static const mp_arg_t show_allowed_args[] = {
{ MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_delay, MP_ARG_INT, {.u_int = DEFAULT_PRINT_SPEED} },
{ MP_QSTR_clear, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_loop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// Parse the args.
microbit_display_obj_t *self = (microbit_display_obj_t*)pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(show_allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(show_allowed_args), show_allowed_args, args);
mp_obj_t image = args[0].u_obj;
mp_int_t delay = args[1].u_int;
bool clear = args[2].u_bool;
bool wait = args[3].u_bool;
bool loop = args[4].u_bool;
if (MP_OBJ_IS_STR(image)) {
// arg is a string object
mp_uint_t len;
const char *str = mp_obj_str_get_data(image, &len);
if (len == 0) {
// There are no chars; do nothing.
return mp_const_none;
} else if (len == 1) {
if (!clear && !loop) {
// A single char; convert to an image and print that.
image = microbit_image_for_char(str[0]);
goto single_image_immediate;
}
}
image = microbit_string_facade(image);
} else if (mp_obj_get_type(image) == &microbit_image_type) {
if (!clear && !loop) {
goto single_image_immediate;
}
image = mp_obj_new_tuple(1, &image);
}
// iterable:
if (args[4].u_bool) { /*loop*/
image = microbit_repeat_iterator(image);
}
microbit_display_animate(self, image, delay, clear, wait);
return mp_const_none;
single_image_immediate:
microbit_display_show(self, (microbit_image_obj_t *)image);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(microbit_display_show_obj, 1, microbit_display_show_func);
static uint8_t async_mode;
static mp_obj_t async_iterator = NULL;
// Record if an error occurs in async animation. Unfortunately there is no way to report this.
static volatile bool wakeup_event = false;
static mp_uint_t async_delay = 1000;
static mp_uint_t async_tick = 0;
static bool async_clear = false;
bool microbit_display_active_animation(void) {
return async_mode == ASYNC_MODE_ANIMATION;
}
STATIC void async_stop(void) {
async_iterator = NULL;
async_mode = ASYNC_MODE_STOPPED;
async_tick = 0;
async_delay = 1000;
async_clear = false;
MP_STATE_PORT(async_data)[0] = NULL;
MP_STATE_PORT(async_data)[1] = NULL;
wakeup_event = true;
}
STATIC void wait_for_event() {
while (!wakeup_event) {
// allow CTRL-C to stop the animation
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
async_stop();
return;
}
__WFI();
}
wakeup_event = false;
}
struct DisplayPoint {
uint8_t x;
uint8_t y;
};
#define NO_CONN 0
#define ROW_COUNT 3
#define COLUMN_COUNT 9
static const DisplayPoint display_map[COLUMN_COUNT][ROW_COUNT] = {
{{0,0}, {4,2}, {2,4}},
{{2,0}, {0,2}, {4,4}},
{{4,0}, {2,2}, {0,4}},
{{4,3}, {1,0}, {0,1}},
{{3,3}, {3,0}, {1,1}},
{{2,3}, {3,4}, {2,1}},
{{1,3}, {1,4}, {3,1}},
{{0,3}, {NO_CONN,NO_CONN}, {4,1}},
{{1,2}, {NO_CONN,NO_CONN}, {3,2}}
};
#define MIN_COLUMN_PIN 4
#define COLUMN_PINS_MASK 0x1ff0
#define MIN_ROW_PIN 13
#define MAX_ROW_PIN 15
#define ROW_PINS_MASK 0xe000
inline void microbit_display_obj_t::setPinsForRow(uint8_t brightness) {
if (brightness == 0) {
nrf_gpio_pins_clear(COLUMN_PINS_MASK & ~this->pins_for_brightness[brightness]);
} else {
nrf_gpio_pins_set(this->pins_for_brightness[brightness]);
}
}
/* This is the primary PWM driver/display driver. It will operate on one row
* (9 pins) per invocation. It will turn on LEDs with maximum brightness,
* then let the "callback" callback turn off the LEDs as appropriate for the
* required brightness level.
*
* For each row
* Turn off all the LEDs in the previous row
* Set the column bits high (off)
* Set the row strobe low (off)
* Turn on all the LEDs in the current row that have maximum brightness
* Set the row strobe high (on)
* Set some/all column bits low (on)
* Register the PWM callback
* For each callback start with brightness 0
* If brightness 0
* Turn off the LEDs specified at this level
* Else
* Turn on the LEDs specified at this level
* If brightness max
* Disable the PWM callback
* Else
* Re-queue the PWM callback after the appropriate delay
*/
void microbit_display_obj_t::advanceRow() {
/* Clear all of the column bits */
nrf_gpio_pins_set(COLUMN_PINS_MASK);
/* Clear the strobe bit for this row */
nrf_gpio_pin_clear(strobe_row+MIN_ROW_PIN);
/* Move to the next row. Before this, "this row" refers to the row
* manipulated by the previous invocation of this function. After this,
* "this row" refers to the row manipulated by the current invocation of
* this function. */
strobe_row++;
// Reset the row counts and bit mask when we have hit the max.
if (strobe_row == ROW_COUNT) {
strobe_row = 0;
}
// Set pin for this row.
// Prepare row for rendering.
for (int i = 0; i <= MAX_BRIGHTNESS; i++) {
pins_for_brightness[i] = 0;
}
for (int i = 0; i < COLUMN_COUNT; i++) {
int x = display_map[i][strobe_row].x;
int y = display_map[i][strobe_row].y;
uint8_t brightness = microbit_display_obj.image_buffer[x][y];
pins_for_brightness[brightness] |= (1<<(i+MIN_COLUMN_PIN));
}
/* Enable the strobe bit for this row */
nrf_gpio_pin_set(strobe_row+MIN_ROW_PIN);
/* Enable the column bits for all pins that need to be on. */
nrf_gpio_pins_clear(pins_for_brightness[MAX_BRIGHTNESS]);
}
static const uint16_t render_timings[] =
// The scale is (approximately) exponential,
// each step is approx x1.9 greater than the previous.
{ 0, // Bright, Ticks Duration, Relative power
2, // 1, 2, 32µs, inf
2, // 2, 4, 64µs, 200%
4, // 3, 8, 128µs, 200%
7, // 4, 15, 240µs, 187%
13, // 5, 28, 448µs, 187%
25, // 6, 53, 848µs, 189%
49, // 7, 102, 1632µs, 192%
97, // 8, 199, 3184µs, 195%
// Always on 9, 375, 6000µs, 188%
};
#define DISPLAY_TICKER_SLOT 1
/* This is the PWM callback. It is registered by the animation callback and
* will unregister itself when all of the brightness steps are complete. */
static int32_t callback(void) {
microbit_display_obj_t *display = &microbit_display_obj;
mp_uint_t brightness = display->previous_brightness;
display->setPinsForRow(brightness);
brightness += 1;
if (brightness == MAX_BRIGHTNESS) {
clear_ticker_callback(DISPLAY_TICKER_SLOT);
return -1;
}
display->previous_brightness = brightness;
// Return interval (in 16µs ticks) until next callback
return render_timings[brightness];
}
static void draw_object(mp_obj_t obj) {
microbit_display_obj_t *display = (microbit_display_obj_t*)MP_STATE_PORT(async_data)[0];
if (obj == MP_OBJ_STOP_ITERATION) {
if (async_clear) {
microbit_display_show(&microbit_display_obj, BLANK_IMAGE);
async_clear = false;
} else {
async_stop();
}
} else if (mp_obj_get_type(obj) == &microbit_image_type) {
microbit_display_show(display, (microbit_image_obj_t *)obj);
} else if (MP_OBJ_IS_STR(obj)) {
mp_uint_t len;
const char *str = mp_obj_str_get_data(obj, &len);
if (len == 1) {
microbit_display_show(display, microbit_image_for_char(str[0]));
} else {
async_stop();
}
} else {
MP_STATE_VM(mp_pending_exception) = mp_obj_new_exception_msg(&mp_type_TypeError, "not an image.");
async_stop();
}
}
static void microbit_display_update(void) {
async_tick += MILLISECONDS_PER_MACRO_TICK;
if (async_tick < async_delay) {
return;
}
async_tick = 0;
switch (async_mode) {
case ASYNC_MODE_ANIMATION:
{
if (MP_STATE_PORT(async_data)[0] == NULL || MP_STATE_PORT(async_data)[1] == NULL) {
async_stop();
break;
}
/* WARNING: We are executing in an interrupt handler.
* If an exception is raised here then we must hand it to the VM. */
mp_obj_t obj;
nlr_buf_t nlr;
gc_lock();
if (nlr_push(&nlr) == 0) {
obj = mp_iternext_allow_raise(async_iterator);
nlr_pop();
gc_unlock();
} else {
gc_unlock();
if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type),
MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
// An exception other than StopIteration, so set it for the VM to raise later
// If memory error, write an appropriate message.
if (mp_obj_get_type(nlr.ret_val) == &mp_type_MemoryError) {
mp_printf(&mp_plat_print, "Allocation in interrupt handler");
}
MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(nlr.ret_val);
}
obj = MP_OBJ_STOP_ITERATION;
}
draw_object(obj);
break;
}
case ASYNC_MODE_CLEAR:
microbit_display_show(&microbit_display_obj, BLANK_IMAGE);
async_stop();
break;
}
}
#define GREYSCALE_MASK ((1<<MAX_BRIGHTNESS)-2)
/* This is the top-level animation/display callback. It is not a registered
* callback. */
void microbit_display_tick(void) {
/* Do nothing if the display is not active. */
if (!microbit_display_obj.active) {
return;
}
microbit_display_obj.advanceRow();
microbit_display_update();
microbit_display_obj.previous_brightness = 0;
if (microbit_display_obj.brightnesses & GREYSCALE_MASK) {
set_ticker_callback(DISPLAY_TICKER_SLOT, callback, 1800);
}
}
void microbit_display_animate(microbit_display_obj_t *self, mp_obj_t iterable, mp_int_t delay, bool clear, bool wait) {
// Reset the repeat state.
MP_STATE_PORT(async_data)[0] = NULL;
MP_STATE_PORT(async_data)[1] = NULL;
async_iterator = mp_getiter(iterable);
async_delay = delay;
async_clear = clear;
MP_STATE_PORT(async_data)[0] = self; // so it doesn't get GC'd
MP_STATE_PORT(async_data)[1] = async_iterator;
wakeup_event = false;
mp_obj_t obj = mp_iternext_allow_raise(async_iterator);
draw_object(obj);
async_tick = 0;
async_mode = ASYNC_MODE_ANIMATION;
if (wait) {
wait_for_event();
}
}
// Delay in ms in between moving display one column to the left.
#define DEFAULT_SCROLL_SPEED 150
void microbit_display_scroll(microbit_display_obj_t *self, const char* str, bool wait) {
mp_obj_t iterable = scrolling_string_image_iterable(str, strlen(str), NULL, false, false);
microbit_display_animate(self, iterable, DEFAULT_SCROLL_SPEED, false, wait);
}
mp_obj_t microbit_display_scroll_func(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t scroll_allowed_args[] = {
{ MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_delay, MP_ARG_INT, {.u_int = DEFAULT_SCROLL_SPEED} },
{ MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_monospace, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_loop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// Parse the args.
microbit_display_obj_t *self = (microbit_display_obj_t*)pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(scroll_allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(scroll_allowed_args), scroll_allowed_args, args);
mp_uint_t len;
const char* str = mp_obj_str_get_data(args[0].u_obj, &len);
mp_obj_t iterable = scrolling_string_image_iterable(str, len, args[0].u_obj, args[3].u_bool /*monospace?*/, args[4].u_bool /*loop*/);
microbit_display_animate(self, iterable, args[1].u_int /*delay*/, false/*clear*/, args[2].u_bool/*wait?*/);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(microbit_display_scroll_obj, 1, microbit_display_scroll_func);
mp_obj_t microbit_display_on_func(mp_obj_t obj) {
microbit_display_obj_t *self = (microbit_display_obj_t*)obj;
/* Try to reclaim the pins we need */
microbit_obj_pin_fail_if_cant_acquire(&microbit_p3_obj);
microbit_obj_pin_fail_if_cant_acquire(&microbit_p4_obj);
microbit_obj_pin_fail_if_cant_acquire(&microbit_p6_obj);
microbit_obj_pin_fail_if_cant_acquire(&microbit_p7_obj);
microbit_obj_pin_fail_if_cant_acquire(&microbit_p9_obj);
microbit_obj_pin_fail_if_cant_acquire(&microbit_p10_obj);
microbit_obj_pin_acquire(&microbit_p3_obj, microbit_pin_mode_display);
microbit_obj_pin_acquire(&microbit_p4_obj, microbit_pin_mode_display);
microbit_obj_pin_acquire(&microbit_p6_obj, microbit_pin_mode_display);
microbit_obj_pin_acquire(&microbit_p7_obj, microbit_pin_mode_display);
microbit_obj_pin_acquire(&microbit_p9_obj, microbit_pin_mode_display);
microbit_obj_pin_acquire(&microbit_p10_obj, microbit_pin_mode_display);
/* Make sure all pins are in the correct state */
microbit_display_init();
/* Re-enable the display loop. This will resume any animations in
* progress and display any static image. */
self->active = true;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_on_obj, microbit_display_on_func);
mp_obj_t microbit_display_off_func(mp_obj_t obj) {
microbit_display_obj_t *self = (microbit_display_obj_t*)obj;
/* Disable the display loop. This will pause any animations in progress.
* It will not prevent a user from attempting to modify the state, but
* modifications will not appear to have any effect until the display loop
* is re-enabled. */
self->active = false;
/* Disable the row strobes, allowing the columns to be used freely for
* GPIO. */
nrf_gpio_pins_clear(ROW_PINS_MASK);
/* Free pins for other uses */
microbit_obj_pin_free(&microbit_p3_obj);
microbit_obj_pin_free(&microbit_p4_obj);
microbit_obj_pin_free(&microbit_p6_obj);
microbit_obj_pin_free(&microbit_p7_obj);
microbit_obj_pin_free(&microbit_p9_obj);
microbit_obj_pin_free(&microbit_p10_obj);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_off_obj, microbit_display_off_func);
mp_obj_t microbit_display_is_on_func(mp_obj_t obj) {
microbit_display_obj_t *self = (microbit_display_obj_t*)obj;
if (self->active) {
return mp_const_true;
}
else {
return mp_const_false;
}
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_is_on_obj, microbit_display_is_on_func);
void microbit_display_clear(void) {
// Reset repeat state, cancel animation and clear screen.
wakeup_event = false;
async_mode = ASYNC_MODE_CLEAR;
async_tick = async_delay - MILLISECONDS_PER_MACRO_TICK;
wait_for_event();
}
mp_obj_t microbit_display_clear_func(void) {
microbit_display_clear();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_clear_obj, microbit_display_clear_func);
void microbit_display_set_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y, mp_int_t bright) {
if (x < 0 || y < 0 || x > 4 || y > 4) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "index out of bounds."));
}
if (bright < 0 || bright > MAX_BRIGHTNESS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "brightness out of bounds."));
}
display->image_buffer[x][y] = bright;
display->brightnesses |= (1 << bright);
}
STATIC mp_obj_t microbit_display_set_pixel_func(mp_uint_t n_args, const mp_obj_t *args) {
(void)n_args;
microbit_display_obj_t *self = (microbit_display_obj_t*)args[0];
microbit_display_set_pixel(self, mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_display_set_pixel_obj, 4, 4, microbit_display_set_pixel_func);
mp_int_t microbit_display_get_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y) {
if (x < 0 || y < 0 || x > 4 || y > 4) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "index out of bounds."));
}
return display->image_buffer[x][y];
}
STATIC mp_obj_t microbit_display_get_pixel_func(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
microbit_display_obj_t *self = (microbit_display_obj_t*)self_in;
return MP_OBJ_NEW_SMALL_INT(microbit_display_get_pixel(self, mp_obj_get_int(x_in), mp_obj_get_int(y_in)));
}
MP_DEFINE_CONST_FUN_OBJ_3(microbit_display_get_pixel_obj, microbit_display_get_pixel_func);
STATIC const mp_map_elem_t microbit_display_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_pixel), (mp_obj_t)&microbit_display_get_pixel_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_pixel), (mp_obj_t)&microbit_display_set_pixel_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_show), (mp_obj_t)&microbit_display_show_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), (mp_obj_t)&microbit_display_scroll_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&microbit_display_clear_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_on), (mp_obj_t)&microbit_display_on_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_off), (mp_obj_t)&microbit_display_off_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_is_on), (mp_obj_t)&microbit_display_is_on_obj },
};
STATIC MP_DEFINE_CONST_DICT(microbit_display_locals_dict, microbit_display_locals_dict_table);
STATIC const mp_obj_type_t microbit_display_type = {
{ &mp_type_type },
.name = MP_QSTR_MicroBitDisplay,
.print = NULL,
.make_new = NULL,
.call = NULL,
.unary_op = NULL,
.binary_op = NULL,
.attr = NULL,
.subscr = NULL,
.getiter = NULL,
.iternext = NULL,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = NULL,
.locals_dict = (mp_obj_dict_t*)&microbit_display_locals_dict,
};
microbit_display_obj_t microbit_display_obj = {
{&microbit_display_type},
{ 0 },
.previous_brightness = 0,
.active = 1,
.strobe_row = 0,
.brightnesses = 0,
.pins_for_brightness = { 0 },
};
void microbit_display_init(void) {
// Set pins as output.
nrf_gpio_range_cfg_output(MIN_COLUMN_PIN, MIN_COLUMN_PIN + COLUMN_COUNT + ROW_COUNT);
}
}

View File

@ -0,0 +1,54 @@
#ifndef __MICROPY_INCLUDED_MICROBIT_DISPLAY_H__
#define __MICROPY_INCLUDED_MICROBIT_DISPLAY_H__
#include "py/runtime.h"
#include "microbitimage.h"
typedef struct _microbit_display_obj_t {
mp_obj_base_t base;
uint8_t image_buffer[5][5];
uint8_t previous_brightness;
bool active;
/* Current row for strobing */
uint8_t strobe_row;
/* boolean histogram of brightness in buffer */
uint16_t brightnesses;
uint16_t pins_for_brightness[MAX_BRIGHTNESS+1];
void advanceRow();
inline void setPinsForRow(uint8_t brightness);
} microbit_display_obj_t;
#define ASYNC_MODE_STOPPED 0
#define ASYNC_MODE_ANIMATION 1
#define ASYNC_MODE_CLEAR 2
extern microbit_display_obj_t microbit_display_obj;
extern "C" {
void microbit_display_show(microbit_display_obj_t *display, microbit_image_obj_t *image);
void microbit_display_animate(microbit_display_obj_t *display, mp_obj_t iterable, mp_int_t delay, bool clear, bool wait);
void microbit_display_scroll(microbit_display_obj_t *display, const char* str, bool wait);
mp_int_t microbit_display_get_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y);
void microbit_display_set_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y, mp_int_t val);
void microbit_display_clear(void);
void microbit_display_init(void);
void microbit_display_tick(void);
bool microbit_display_active_animation(void);
}
#endif // __MICROPY_INCLUDED_MICROBIT_DISPLAY_H__

View File

@ -0,0 +1,973 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Damien George, Mark Shannon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "microbitobj.h"
#include "MicroBitFont.h"
extern "C" {
#include "py/runtime.h"
#include "modmicrobit.h"
#include "microbitimage.h"
#include "py/runtime0.h"
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
const monochrome_5by5_t microbit_blank_image = {
{ &microbit_image_type },
1, 0, 0, 0,
{ 0, 0, 0 }
};
STATIC void microbit_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
mp_printf(print, "Image(");
if (kind == PRINT_STR)
mp_printf(print, "\n ");
mp_printf(print, "'");
for (int y = 0; y < self->height(); ++y) {
for (int x = 0; x < self->width(); ++x) {
mp_printf(print, "%c", "0123456789"[self->getPixelValue(x, y)]);
}
mp_printf(print, ":");
if (kind == PRINT_STR && y < self->height()-1)
mp_printf(print, "'\n '");
}
mp_printf(print, "'");
if (kind == PRINT_STR)
mp_printf(print, "\n");
mp_printf(print, ")");
}
uint8_t monochrome_5by5_t::getPixelValue(mp_int_t x, mp_int_t y) {
unsigned int index = y*5+x;
if (index == 24)
return this->pixel44;
return (this->bits24[index>>3] >> (index&7))&1;
}
uint8_t greyscale_t::getPixelValue(mp_int_t x, mp_int_t y) {
unsigned int index = y*this->width+x;
unsigned int shift = ((index<<2)&4);
return (this->byte_data[index>>1] >> shift)&15;
}
void greyscale_t::setPixelValue(mp_int_t x, mp_int_t y, mp_int_t val) {
unsigned int index = y*this->width+x;
unsigned int shift = ((index<<2)&4);
uint8_t mask = 240 >> shift;
this->byte_data[index>>1] = (this->byte_data[index>>1] & mask) | (val << shift);
}
void greyscale_t::fill(mp_int_t val) {
mp_int_t byte = (val<<4) | val;
for (int i = 0; i < ((this->width*this->height+1)>>1); i++) {
this->byte_data[i] = byte;
}
}
void greyscale_t::clear() {
memset(&this->byte_data, 0, (this->width*this->height+1)>>1);
}
uint8_t microbit_image_obj_t::getPixelValue(mp_int_t x, mp_int_t y) {
if (this->base.five)
return this->monochrome_5by5.getPixelValue(x, y)*MAX_BRIGHTNESS;
else
return this->greyscale.getPixelValue(x, y);
}
mp_int_t microbit_image_obj_t::width() {
if (this->base.five)
return 5;
else
return this->greyscale.width;
}
mp_int_t microbit_image_obj_t::height() {
if (this->base.five)
return 5;
else
return this->greyscale.height;
}
STATIC greyscale_t *greyscale_new(mp_int_t w, mp_int_t h) {
greyscale_t *result = m_new_obj_var(greyscale_t, uint8_t, (w*h+1)>>1);
result->base.type = &microbit_image_type;
result->five = 0;
result->width = w;
result->height = h;
return result;
}
greyscale_t *microbit_image_obj_t::copy() {
mp_int_t w = this->width();
mp_int_t h = this->height();
greyscale_t *result = greyscale_new(w, h);
for (mp_int_t y = 0; y < h; y++) {
for (mp_int_t x = 0; x < w; ++x) {
result->setPixelValue(x,y, this->getPixelValue(x,y));
}
}
return result;
}
greyscale_t *microbit_image_obj_t::invert() {
mp_int_t w = this->width();
mp_int_t h = this->height();
greyscale_t *result = greyscale_new(w, h);
for (mp_int_t y = 0; y < h; y++) {
for (mp_int_t x = 0; x < w; ++x) {
result->setPixelValue(x,y, MAX_BRIGHTNESS - this->getPixelValue(x,y));
}
}
return result;
}
STATIC microbit_image_obj_t *image_from_parsed_str(const char *s, mp_int_t len) {
mp_int_t w = 0;
mp_int_t h = 0;
mp_int_t line_len = 0;
greyscale_t *result;
/*First pass -- Establish metadata */
for (int i = 0; i < len; i++) {
char c = s[i];
if (c == '\n' || c == ':') {
w = max(line_len, w);
line_len = 0;
++h;
} else if (c == ' ') {
++line_len;
} else if ('c' >= '0' && c <= '9') {
++line_len;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"Unexpected character in Image definition."));
}
}
if (line_len) {
// Omitted trailing terminator
++h;
w = max(line_len, w);
}
result = greyscale_new(w, h);
mp_int_t x = 0;
mp_int_t y = 0;
/* Second pass -- Fill in data */
for (int i = 0; i < len; i++) {
char c = s[i];
if (c == '\n' || c == ':') {
while (x < w) {
result->setPixelValue(x, y, 0);
x++;
}
++y;
x = 0;
} else if (c == ' ') {
/* Treat spaces as 0 */
result->setPixelValue(x, y, 0);
++x;
} else if ('c' >= '0' && c <= '9') {
result->setPixelValue(x, y, c - '0');
++x;
}
}
if (y < h) {
while (x < w) {
result->setPixelValue(x, y, 0);
x++;
}
}
return (microbit_image_obj_t *)result;
}
STATIC mp_obj_t microbit_image_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
(void)type_in;
mp_arg_check_num(n_args, n_kw, 0, 3, false);
switch (n_args) {
case 0: {
greyscale_t *image = greyscale_new(5, 5);
image->clear();
return image;
}
case 1: {
if (MP_OBJ_IS_STR(args[0])) {
// arg is a string object
mp_uint_t len;
const char *str = mp_obj_str_get_data(args[0], &len);
// make image from string
if (len == 1) {
/* For a single charater, return the font glyph */
return microbit_image_for_char(str[0]);
} else {
/* Otherwise parse the image description string */
return image_from_parsed_str(str, len);
}
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"Image(s) takes a string."));
}
}
case 2:
case 3: {
mp_int_t w = mp_obj_get_int(args[0]);
mp_int_t h = mp_obj_get_int(args[1]);
greyscale_t *image = greyscale_new(w, h);
if (n_args == 2) {
image->clear();
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
if (w < 0 || h < 0 || (size_t)(w * h) != bufinfo.len) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"image data is incorrect size"));
}
mp_int_t i = 0;
for (mp_int_t y = 0; y < h; y++) {
for (mp_int_t x = 0; x < w; ++x) {
uint8_t val = min(((const uint8_t*)bufinfo.buf)[i], MAX_BRIGHTNESS);
image->setPixelValue(x, y, val);
++i;
}
}
}
return image;
}
default: {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"Image() takes 0 to 3 arguments"));
}
}
}
static void clear_rect(greyscale_t *img, mp_int_t x0, mp_int_t y0,mp_int_t x1, mp_int_t y1) {
for (int i = x0; i < x1; ++i) {
for (int j = y0; j < y1; ++j) {
img->setPixelValue(i, j, 0);
}
}
}
STATIC void image_blit(microbit_image_obj_t *src, greyscale_t *dest, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h, mp_int_t xdest, mp_int_t ydest) {
if (w < 0)
w = 0;
if (h < 0)
h = 0;
mp_int_t intersect_x0 = max(max(0, x), -xdest);
mp_int_t intersect_y0 = max(max(0, y), -ydest);
mp_int_t intersect_x1 = min(min(dest->width+x-xdest, src->width()), x+w);
mp_int_t intersect_y1 = min(min(dest->height+y-ydest, src->height()), y+h);
mp_int_t xstart, xend, ystart, yend, xdel, ydel;
mp_int_t clear_x0 = max(0, xdest);
mp_int_t clear_y0 = max(0, ydest);
mp_int_t clear_x1 = min(dest->width, xdest+w);
mp_int_t clear_y1 = min(dest->height, ydest+h);
if (intersect_x0 >= intersect_x1 || intersect_y0 >= intersect_y1) {
// Nothing to copy
clear_rect(dest, clear_x0, clear_y0, clear_x1, clear_y1);
return;
}
if (x > xdest) {
xstart = intersect_x0; xend = intersect_x1; xdel = 1;
} else {
xstart = intersect_x1-1; xend = intersect_x0-1; xdel = -1;
}
if (y > ydest) {
ystart = intersect_y0; yend = intersect_y1; ydel = 1;
} else {
ystart = intersect_y1-1; yend = intersect_y0-1; ydel = -1;
}
for (int i = xstart; i != xend; i += xdel) {
for (int j = ystart; j != yend; j += ydel) {
int val = src->getPixelValue(i, j);
dest->setPixelValue(i+xdest-x, j+ydest-y, val);
}
}
// Adjust intersection rectange to dest
intersect_x0 += xdest-x;
intersect_y0 += ydest-y;
intersect_x1 += xdest-x;
intersect_y1 += ydest-y;
// Clear four rectangles in the cleared area surrounding the copied area.
clear_rect(dest, clear_x0, clear_y0, intersect_x0, intersect_y1);
clear_rect(dest, clear_x0, intersect_y1, intersect_x1, clear_y1);
clear_rect(dest, intersect_x1, intersect_y0, clear_x1, clear_y1);
clear_rect(dest, intersect_x0, clear_y0, clear_x1, intersect_y0);
}
greyscale_t *image_shift(microbit_image_obj_t *self, mp_int_t x, mp_int_t y) {
greyscale_t *result = greyscale_new(self->width(), self->width());
image_blit(self, result, x, y, self->width(), self->width(), 0, 0);
return result;
}
STATIC microbit_image_obj_t *image_crop(microbit_image_obj_t *img, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h) {
if (w < 0)
w = 0;
if (h < 0)
h = 0;
greyscale_t *result = greyscale_new(w, h);
image_blit(img, result, x, y, w, h, 0, 0);
return (microbit_image_obj_t *)result;
}
mp_obj_t microbit_image_width(mp_obj_t self_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
return MP_OBJ_NEW_SMALL_INT(self->width());
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_width_obj, microbit_image_width);
mp_obj_t microbit_image_height(mp_obj_t self_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
return MP_OBJ_NEW_SMALL_INT(self->height());
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_height_obj, microbit_image_height);
mp_obj_t microbit_image_get_pixel(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
mp_int_t x = mp_obj_get_int(x_in);
mp_int_t y = mp_obj_get_int(y_in);
if (x < 0 || y < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"index cannot be negative"));
}
if (x < self->width() && y < self->height()) {
return MP_OBJ_NEW_SMALL_INT(self->getPixelValue(x, y));
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "index too large"));
}
MP_DEFINE_CONST_FUN_OBJ_3(microbit_image_get_pixel_obj, microbit_image_get_pixel);
/* Raise an exception if not mutable */
static void check_mutability(microbit_image_obj_t *self) {
if (self->base.five) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "image cannot be modified (try copying first)"));
}
}
mp_obj_t microbit_image_set_pixel(mp_uint_t n_args, const mp_obj_t *args) {
(void)n_args;
microbit_image_obj_t *self = (microbit_image_obj_t*)args[0];
check_mutability(self);
mp_int_t x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]);
if (x < 0 || y < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"index cannot be negative"));
}
mp_int_t bright = mp_obj_get_int(args[3]);
if (bright < 0 || bright > MAX_BRIGHTNESS)
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "brightness out of bounds."));
if (x < self->width() && y < self->height()) {
self->greyscale.setPixelValue(x, y, bright);
return mp_const_none;
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "index too large"));
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_set_pixel_obj, 4, 4, microbit_image_set_pixel);
mp_obj_t microbit_image_fill(mp_obj_t self_in, mp_obj_t n_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
check_mutability(self);
mp_int_t n = mp_obj_get_int(n_in);
if (n < 0 || n > MAX_BRIGHTNESS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "brightness out of bounds."));
}
self->greyscale.fill(n);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_fill_obj, microbit_image_fill);
mp_obj_t microbit_image_blit(mp_uint_t n_args, const mp_obj_t *args) {
microbit_image_obj_t *self = (microbit_image_obj_t*)args[0];
check_mutability(self);
mp_obj_t src = args[1];
if (mp_obj_get_type(src) != &microbit_image_type) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting an image"));
}
if (n_args == 7) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"must specify both offsets"));
}
mp_int_t x = mp_obj_get_int(args[2]);
mp_int_t y = mp_obj_get_int(args[3]);
mp_int_t w = mp_obj_get_int(args[4]);
mp_int_t h = mp_obj_get_int(args[5]);
if (w < 0 || h < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"size cannot be negative"));
}
mp_int_t xdest;
mp_int_t ydest;
if (n_args == 6) {
xdest = 0;
ydest = 0;
} else {
xdest = mp_obj_get_int(args[6]);
ydest = mp_obj_get_int(args[7]);
}
image_blit((microbit_image_obj_t *)src, &(self->greyscale), x, y, w, h, xdest, ydest);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_blit_obj, 6, 8, microbit_image_blit);
mp_obj_t microbit_image_crop(mp_uint_t n_args, const mp_obj_t *args) {
(void)n_args;
microbit_image_obj_t *self = (microbit_image_obj_t*)args[0];
mp_int_t x0 = mp_obj_get_int(args[1]);
mp_int_t y0 = mp_obj_get_int(args[2]);
mp_int_t x1 = mp_obj_get_int(args[3]);
mp_int_t y1 = mp_obj_get_int(args[4]);
return image_crop(self, x0, y0, x1, y1);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_crop_obj, 5, 5, microbit_image_crop);
mp_obj_t microbit_image_shift_left(mp_obj_t self_in, mp_obj_t n_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
mp_int_t n = mp_obj_get_int(n_in);
return image_shift(self, n, 0);
}
MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_left_obj, microbit_image_shift_left);
mp_obj_t microbit_image_shift_right(mp_obj_t self_in, mp_obj_t n_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
mp_int_t n = mp_obj_get_int(n_in);
return image_shift(self, -n, 0);
}
MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_right_obj, microbit_image_shift_right);
mp_obj_t microbit_image_shift_up(mp_obj_t self_in, mp_obj_t n_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
mp_int_t n = mp_obj_get_int(n_in);
return image_shift(self, 0, n);
}
MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_up_obj, microbit_image_shift_up);
mp_obj_t microbit_image_shift_down(mp_obj_t self_in, mp_obj_t n_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
mp_int_t n = mp_obj_get_int(n_in);
return image_shift(self, 0, -n);
}
MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_down_obj, microbit_image_shift_down);
mp_obj_t microbit_image_copy(mp_obj_t self_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
return self->copy();
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_copy_obj, microbit_image_copy);
mp_obj_t microbit_image_invert(mp_obj_t self_in) {
microbit_image_obj_t *self = (microbit_image_obj_t*)self_in;
return self->invert();
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_invert_obj, microbit_image_invert);
STATIC const mp_map_elem_t microbit_image_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_width), (mp_obj_t)&microbit_image_width_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_height), (mp_obj_t)&microbit_image_height_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_pixel), (mp_obj_t)&microbit_image_get_pixel_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_pixel), (mp_obj_t)&microbit_image_set_pixel_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_shift_left), (mp_obj_t)&microbit_image_shift_left_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_shift_right), (mp_obj_t)&microbit_image_shift_right_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_shift_up), (mp_obj_t)&microbit_image_shift_up_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_shift_down), (mp_obj_t)&microbit_image_shift_down_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&microbit_image_copy_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_crop), (mp_obj_t)&microbit_image_crop_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_invert), (mp_obj_t)&microbit_image_invert_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_fill), (mp_obj_t)&microbit_image_fill_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_blit), (mp_obj_t)&microbit_image_blit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HEART), (mp_obj_t)&microbit_const_image_heart_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HEART_SMALL), (mp_obj_t)&microbit_const_image_heart_small_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HAPPY), (mp_obj_t)&microbit_const_image_happy_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SMILE), (mp_obj_t)&microbit_const_image_smile_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SAD), (mp_obj_t)&microbit_const_image_sad_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CONFUSED), (mp_obj_t)&microbit_const_image_confused_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ANGRY), (mp_obj_t)&microbit_const_image_angry_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ASLEEP), (mp_obj_t)&microbit_const_image_asleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SURPRISED), (mp_obj_t)&microbit_const_image_surprised_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SILLY), (mp_obj_t)&microbit_const_image_silly_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FABULOUS), (mp_obj_t)&microbit_const_image_fabulous_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MEH), (mp_obj_t)&microbit_const_image_meh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_YES), (mp_obj_t)&microbit_const_image_yes_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_NO), (mp_obj_t)&microbit_const_image_no_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK12), (mp_obj_t)&microbit_const_image_clock12_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK1), (mp_obj_t)&microbit_const_image_clock1_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK2), (mp_obj_t)&microbit_const_image_clock2_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK3), (mp_obj_t)&microbit_const_image_clock3_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK4), (mp_obj_t)&microbit_const_image_clock4_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK5), (mp_obj_t)&microbit_const_image_clock5_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK6), (mp_obj_t)&microbit_const_image_clock6_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK7), (mp_obj_t)&microbit_const_image_clock7_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK8), (mp_obj_t)&microbit_const_image_clock8_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK9), (mp_obj_t)&microbit_const_image_clock9_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK10), (mp_obj_t)&microbit_const_image_clock10_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CLOCK11), (mp_obj_t)&microbit_const_image_clock11_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_N), (mp_obj_t)&microbit_const_image_arrow_n_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_NE), (mp_obj_t)&microbit_const_image_arrow_ne_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_E), (mp_obj_t)&microbit_const_image_arrow_e_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_SE), (mp_obj_t)&microbit_const_image_arrow_se_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_S), (mp_obj_t)&microbit_const_image_arrow_s_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_SW), (mp_obj_t)&microbit_const_image_arrow_sw_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_W), (mp_obj_t)&microbit_const_image_arrow_w_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARROW_NW), (mp_obj_t)&microbit_const_image_arrow_nw_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TRIANGLE), (mp_obj_t)&microbit_const_image_triangle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TRIANGLE_LEFT), (mp_obj_t)&microbit_const_image_triangle_left_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CHESSBOARD), (mp_obj_t)&microbit_const_image_chessboard_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DIAMOND), (mp_obj_t)&microbit_const_image_diamond_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DIAMOND_SMALL), (mp_obj_t)&microbit_const_image_diamond_small_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SQUARE), (mp_obj_t)&microbit_const_image_square_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SQUARE_SMALL), (mp_obj_t)&microbit_const_image_square_small_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RABBIT), (mp_obj_t)&microbit_const_image_rabbit },
{ MP_OBJ_NEW_QSTR(MP_QSTR_COW), (mp_obj_t)&microbit_const_image_cow },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MUSIC_CROTCHET), (mp_obj_t)&microbit_const_image_music_crotchet_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MUSIC_QUAVER), (mp_obj_t)&microbit_const_image_music_quaver_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MUSIC_QUAVERS), (mp_obj_t)&microbit_const_image_music_quavers_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PITCHFORK), (mp_obj_t)&microbit_const_image_pitchfork_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_XMAS), (mp_obj_t)&microbit_const_image_xmas_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PACMAN), (mp_obj_t)&microbit_const_image_pacman_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TARGET), (mp_obj_t)&microbit_const_image_target_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALL_CLOCKS), (mp_obj_t)&microbit_const_image_all_clocks_tuple_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALL_ARROWS), (mp_obj_t)&microbit_const_image_all_arrows_tuple_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TSHIRT), (mp_obj_t)&microbit_const_image_tshirt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ROLLERSKATE), (mp_obj_t)&microbit_const_image_rollerskate_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DUCK), (mp_obj_t)&microbit_const_image_duck_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HOUSE), (mp_obj_t)&microbit_const_image_house_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TORTOISE), (mp_obj_t)&microbit_const_image_tortoise_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BUTTERFLY), (mp_obj_t)&microbit_const_image_butterfly_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_STICKFIGURE), (mp_obj_t)&microbit_const_image_stickfigure_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_GHOST), (mp_obj_t)&microbit_const_image_ghost_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SWORD), (mp_obj_t)&microbit_const_image_sword_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_GIRAFFE), (mp_obj_t)&microbit_const_image_giraffe_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SKULL), (mp_obj_t)&microbit_const_image_skull_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UMBRELLA), (mp_obj_t)&microbit_const_image_umbrella_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SNAKE), (mp_obj_t)&microbit_const_image_snake_obj },
};
STATIC MP_DEFINE_CONST_DICT(microbit_image_locals_dict, microbit_image_locals_dict_table);
#define THE_FONT MicroBitFont::defaultFont
#define ASCII_START 32
#define ASCII_END 126
STATIC const unsigned char *get_font_data_from_char(char c) {
if (c < ASCII_START || c > ASCII_END) {
c = '?';
}
int offset = (c-ASCII_START) * 5;
return THE_FONT + offset;
}
STATIC mp_int_t get_pixel_from_font_data(const unsigned char *data, int x, int y) {
/* The following logic belongs in MicroBitFont */
return ((data[y]>>(4-x))&1);
}
void microbit_image_set_from_char(greyscale_t *img, char c) {
const unsigned char *data = get_font_data_from_char(c);
for (int x = 0; x < 5; ++x) {
for (int y = 0; y < 5; ++y) {
img->setPixelValue(x, y, get_pixel_from_font_data(data, x, y)*MAX_BRIGHTNESS);
}
}
}
microbit_image_obj_t *microbit_image_for_char(char c) {
greyscale_t *result = greyscale_new(5,5);
microbit_image_set_from_char(result, c);
return (microbit_image_obj_t *)result;
}
microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t fval) {
if (fval < 0)
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Brightness multiplier must not be negative."));
greyscale_t *result = greyscale_new(lhs->width(), lhs->height());
for (int x = 0; x < lhs->width(); ++x) {
for (int y = 0; y < lhs->width(); ++y) {
int val = min((int)lhs->getPixelValue(x,y)*fval+0.5, MAX_BRIGHTNESS);
result->setPixelValue(x, y, val);
}
}
return (microbit_image_obj_t *)result;
}
microbit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_image_obj_t *rhs, bool add) {
mp_int_t h = lhs->height();
mp_int_t w = lhs->width();
if (rhs->height() != h || lhs->width() != w) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Images must be the same size."));
}
greyscale_t *result = greyscale_new(w, h);
for (int x = 0; x < w; ++x) {
for (int y = 0; y < h; ++y) {
int val;
int lval = lhs->getPixelValue(x,y);
int rval = rhs->getPixelValue(x,y);
if (add)
val = min(lval + rval, MAX_BRIGHTNESS);
else
val = max(0, lval - rval);
result->setPixelValue(x, y, val);
}
}
return (microbit_image_obj_t *)result;
}
STATIC mp_obj_t image_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (mp_obj_get_type(lhs_in) != &microbit_image_type) {
return MP_OBJ_NULL; // op not supported
}
microbit_image_obj_t *lhs = (microbit_image_obj_t *)lhs_in;
switch(op) {
case MP_BINARY_OP_ADD:
case MP_BINARY_OP_SUBTRACT:
break;
case MP_BINARY_OP_MULTIPLY:
return microbit_image_dim(lhs, mp_obj_get_float(rhs_in));
case MP_BINARY_OP_TRUE_DIVIDE:
return microbit_image_dim(lhs, 1.0/mp_obj_get_float(rhs_in));
default:
return MP_OBJ_NULL; // op not supported
}
if (mp_obj_get_type(rhs_in) != &microbit_image_type) {
return MP_OBJ_NULL; // op not supported
}
return microbit_image_sum(lhs, (microbit_image_obj_t *)rhs_in, op == MP_BINARY_OP_ADD);
}
const mp_obj_type_t microbit_image_type = {
{ &mp_type_type },
.name = MP_QSTR_MicroBitImage,
.print = microbit_image_print,
.make_new = microbit_image_make_new,
.call = NULL,
.unary_op = NULL,
.binary_op = image_binary_op,
.attr = NULL,
.subscr = NULL,
.getiter = NULL,
.iternext = NULL,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = NULL,
.locals_dict = (mp_obj_dict_t*)&microbit_image_locals_dict,
};
typedef struct _scrolling_string_t {
mp_obj_base_t base;
char const *str;
mp_uint_t len;
mp_obj_t ref;
bool monospace;
bool repeat;
} scrolling_string_t;
typedef struct _scrolling_string_iterator_t {
mp_obj_base_t base;
mp_obj_t ref;
greyscale_t *img;
char const *next_char;
char const *start;
char const *end;
uint8_t offset;
uint8_t offset_limit;
bool monospace;
bool repeat;
char right;
} scrolling_string_iterator_t;
extern const mp_obj_type_t microbit_scrolling_string_type;
extern const mp_obj_type_t microbit_scrolling_string_iterator_type;
mp_obj_t scrolling_string_image_iterable(const char* str, mp_uint_t len, mp_obj_t ref, bool monospace, bool repeat) {
scrolling_string_t *result = m_new_obj(scrolling_string_t);
result->base.type = &microbit_scrolling_string_type;
result->str = str;
result->len = len;
result->ref = ref;
result->monospace = monospace;
result->repeat = repeat;
return result;
}
STATIC int font_column_non_blank(const unsigned char *font_data, unsigned int col) {
for (int y = 0; y < 5; ++y) {
if (get_pixel_from_font_data(font_data, col, y)) {
return 1;
}
}
return 0;
}
/* Not strictly the rightmost non-blank column, but the rightmost in columns 2,3 or 4. */
STATIC unsigned int rightmost_non_blank_column(const unsigned char *font_data) {
if (font_column_non_blank(font_data, 4)) {
return 4;
}
if (font_column_non_blank(font_data, 3)) {
return 3;
}
return 2;
}
static void restart(scrolling_string_iterator_t *iter) {
iter->next_char = iter->start;
iter->offset = 0;
if (iter->start < iter->end) {
iter->right = *iter->next_char;
if (iter->monospace) {
iter->offset_limit = 5;
} else {
iter->offset_limit = rightmost_non_blank_column(get_font_data_from_char(iter->right)) + 1;
}
} else {
iter->right = ' ';
iter->offset_limit = 5;
}
}
STATIC mp_obj_t get_microbit_scrolling_string_iter(mp_obj_t o_in) {
scrolling_string_t *str = (scrolling_string_t *)o_in;
scrolling_string_iterator_t *result = m_new_obj(scrolling_string_iterator_t);
result->base.type = &microbit_scrolling_string_iterator_type;
result->img = greyscale_new(5,5);
result->start = str->str;
result->ref = str->ref;
result->monospace = str->monospace;
result->end = result->start + str->len;
result->repeat = str->repeat;
restart(result);
return result;
}
STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) {
scrolling_string_iterator_t *iter = (scrolling_string_iterator_t *)o_in;
if (iter->next_char == iter->end && iter->offset == 5) {
if (iter->repeat) {
restart(iter);
iter->img->clear();
} else {
return MP_OBJ_STOP_ITERATION;
}
}
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 5; y++) {
iter->img->setPixelValue(x, y, iter->img->getPixelValue(x+1, y));
}
}
for (int y = 0; y < 5; y++) {
iter->img->setPixelValue(4, y, 0);
}
const unsigned char *font_data;
if (iter->offset < iter->offset_limit) {
font_data = get_font_data_from_char(iter->right);
for (int y = 0; y < 5; ++y) {
int pix = get_pixel_from_font_data(font_data, iter->offset, y)*MAX_BRIGHTNESS;
iter->img->setPixelValue(4, y, pix);
}
} else if (iter->offset == iter->offset_limit) {
++iter->next_char;
if (iter->next_char == iter->end) {
iter->right = ' ';
iter->offset_limit = 5;
iter->offset = 0;
} else {
iter->right = *iter->next_char;
font_data = get_font_data_from_char(iter->right);
if (iter->monospace) {
iter->offset = -1;
iter->offset_limit = 5;
} else {
iter->offset = -font_column_non_blank(font_data, 0);
iter->offset_limit = rightmost_non_blank_column(font_data)+1;
}
}
}
++iter->offset;
return iter->img;
}
const mp_obj_type_t microbit_scrolling_string_type = {
{ &mp_type_type },
.name = MP_QSTR_ScrollingString,
.print = NULL,
.make_new = NULL,
.call = NULL,
.unary_op = NULL,
.binary_op = NULL,
.attr = NULL,
.subscr = NULL,
.getiter = get_microbit_scrolling_string_iter,
.iternext = NULL,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = NULL,
.locals_dict = NULL,
};
const mp_obj_type_t microbit_scrolling_string_iterator_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.print = NULL,
.make_new = NULL,
.call = NULL,
.unary_op = NULL,
.binary_op = NULL,
.attr = NULL,
.subscr = NULL,
.getiter = mp_identity,
.iternext = microbit_scrolling_string_iter_next,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = NULL,
.locals_dict = NULL,
};
/** Facade types to present a string as a sequence of images.
* These are necessary to avoid allocation during iteration,
* which may happen in interrupt handlers.
*/
typedef struct _string_image_facade_t {
mp_obj_base_t base;
mp_obj_t string;
greyscale_t *image;
} string_image_facade_t;
static mp_obj_t string_image_facade_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
if (value == MP_OBJ_SENTINEL) {
// Fill in image
string_image_facade_t *self = (string_image_facade_t *)self_in;
mp_uint_t len;
const char *text = mp_obj_str_get_data(self->string, &len);
mp_uint_t index = mp_get_index(self->base.type, len, index_in, false);
microbit_image_set_from_char(self->image, text[index]);
return self->image;
} else {
return MP_OBJ_NULL; // op not supported
}
}
static mp_obj_t facade_unary_op(mp_uint_t op, mp_obj_t self_in) {
string_image_facade_t *self = (string_image_facade_t *)self_in;
switch (op) {
case MP_UNARY_OP_LEN:
return mp_obj_len(self->string);
default: return MP_OBJ_NULL; // op not supported
}
}
static mp_obj_t microbit_facade_iterator(mp_obj_t iterable);
const mp_obj_type_t string_image_facade_type = {
{ &mp_type_type },
.name = MP_QSTR_Facade,
.print = NULL,
.make_new = NULL,
.call = NULL,
.unary_op = facade_unary_op,
.binary_op = NULL,
.attr = NULL,
.subscr = string_image_facade_subscr,
.getiter = microbit_facade_iterator,
.iternext = NULL,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = NULL,
NULL
};
typedef struct _facade_iterator_t {
mp_obj_base_t base;
mp_obj_t string;
mp_uint_t index;
greyscale_t *image;
} facade_iterator_t;
mp_obj_t microbit_string_facade(mp_obj_t string) {
string_image_facade_t *result = m_new_obj(string_image_facade_t);
result->base.type = &string_image_facade_type;
result->string = string;
result->image = greyscale_new(5,5);
return result;
}
static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) {
facade_iterator_t *iter = (facade_iterator_t *)iter_in;
mp_uint_t len;
const char *text = mp_obj_str_get_data(iter->string, &len);
if (iter->index >= len) {
return MP_OBJ_STOP_ITERATION;
}
microbit_image_set_from_char(iter->image, text[iter->index]);
iter->index++;
return iter->image;
}
const mp_obj_type_t microbit_facade_iterator_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.print = NULL,
.make_new = NULL,
.call = NULL,
.unary_op = NULL,
.binary_op = NULL,
.attr = NULL,
.subscr = NULL,
.getiter = mp_identity,
.iternext = microbit_facade_iter_next,
.buffer_p = {NULL},
.stream_p = NULL,
.bases_tuple = NULL,
NULL
};
mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in) {
facade_iterator_t *result = m_new_obj(facade_iterator_t);
string_image_facade_t *iterable = (string_image_facade_t *)iterable_in;
result->base.type = &microbit_facade_iterator_type;
result->string = iterable->string;
result->image = iterable->image;
result->index = 0;
return result;
}
}

View File

@ -0,0 +1,92 @@
#ifndef __MICROPY_INCLUDED_MICROBIT_IMAGE_H__
#define __MICROPY_INCLUDED_MICROBIT_IMAGE_H__
#include "py/runtime.h"
#define MAX_BRIGHTNESS 9
/** Monochrome images are immutable, which means that
* we only need one bit per pixel which saves quite a lot
* of memory */
/* we reserve a couple of bits, so we won't need to modify the
* layout if we need to add more functionality or subtypes. */
#define TYPE_AND_FLAGS \
mp_obj_base_t base; \
uint8_t five:1; \
uint8_t reserved1:1; \
uint8_t reserved2:1
typedef struct _image_base_t {
TYPE_AND_FLAGS;
} image_base_t;
typedef struct _monochrome_5by5_t {
TYPE_AND_FLAGS;
uint8_t pixel44: 1;
uint8_t bits24[3];
/* This is an internal method it is up to the caller to validate the inputs */
uint8_t getPixelValue(mp_int_t x, mp_int_t y);
} monochrome_5by5_t;
typedef struct _greyscale_t {
TYPE_AND_FLAGS;
uint8_t height;
uint8_t width;
uint8_t byte_data[]; /* Static initializer for this will have to be C, not C++ */
void clear();
/* Thiese are internal methods and it is up to the caller to validate the inputs */
uint8_t getPixelValue(mp_int_t x, mp_int_t y);
void setPixelValue(mp_int_t x, mp_int_t y, mp_int_t val);
void fill(mp_int_t val);
} greyscale_t;
typedef union _microbit_image_obj_t {
image_base_t base;
monochrome_5by5_t monochrome_5by5;
greyscale_t greyscale;
mp_int_t height();
mp_int_t width();
greyscale_t *copy();
greyscale_t *invert();
/* This is an internal method it is up to the caller to validate the inputs */
uint8_t getPixelValue(mp_int_t x, mp_int_t y);
} microbit_image_obj_t;
/** Return a facade object that presents the string as a sequence of images */
mp_obj_t microbit_string_facade(mp_obj_t string);
void microbit_image_set_from_char(greyscale_t *img, char c);
microbit_image_obj_t *microbit_image_for_char(char c);
mp_obj_t microbit_image_slice(microbit_image_obj_t *img, mp_int_t start, mp_int_t width, mp_int_t stride);
/* ref exists so that we can pull a string out of an object and not have it GC'ed while oterating over it */
mp_obj_t scrolling_string_image_iterable(const char* str, mp_uint_t len, mp_obj_t ref, bool monospace, bool repeat);
#define SMALL_IMAGE(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p44) \
{ \
{ &microbit_image_type }, \
1, 0, 0, (p44), \
{ \
(p0)|((p1)<<1)|((p2)<<2)|((p3)<<3)|((p4)<<4)|((p5)<<5)|((p6)<<6)|((p7)<<7), \
(p8)|((p9)<<1)|((p10)<<2)|((p11)<<3)|((p12)<<4)|((p13)<<5)|((p14)<<6)|((p15)<<7), \
(p16)|((p17)<<1)|((p18)<<2)|((p19)<<3)|((p20)<<4)|((p21)<<5)|((p22)<<6)|((p23)<<7) \
} \
}
extern const monochrome_5by5_t microbit_blank_image;
extern const monochrome_5by5_t microbit_const_image_heart_obj;
#define BLANK_IMAGE (microbit_image_obj_t *)(&microbit_blank_image)
#define HEART_IMAGE (microbit_image_obj_t *)(&microbit_const_image_heart_obj)
#define HAPPY_IMAGE (microbit_image_obj_t *)(&microbit_const_image_happy_obj)
microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t fval);
microbit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_image_obj_t *rhs, bool add);
#endif // __MICROPY_INCLUDED_MICROBIT_IMAGE_H__

View File

@ -0,0 +1,158 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "mbed.h"
extern "C" {
#include "py/nlr.h"
#include "py/obj.h"
#include "py/mphal.h"
#include "modmicrobit.h"
#include "microbitdisplay.h"
#include "microbitimage.h"
extern uint32_t ticks;
STATIC mp_obj_t microbit_reset_(void) {
NVIC_SystemReset();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(microbit_reset_obj, microbit_reset_);
STATIC mp_obj_t microbit_sleep(mp_obj_t ms_in) {
mp_int_t ms;
if (mp_obj_is_integer(ms_in)) {
ms = mp_obj_get_int(ms_in);
} else {
ms = (mp_int_t)mp_obj_get_float(ms_in);
}
if (ms > 0) {
mp_hal_delay_ms(ms);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(microbit_sleep_obj, microbit_sleep);
STATIC mp_obj_t microbit_running_time(void) {
return MP_OBJ_NEW_SMALL_INT(ticks);
}
MP_DEFINE_CONST_FUN_OBJ_0(microbit_running_time_obj, microbit_running_time);
static const monochrome_5by5_t panic = SMALL_IMAGE(
1,1,0,1,1,
1,1,0,1,1,
0,0,0,0,0,
0,1,1,1,0,
1,0,0,0,1
);
STATIC mp_obj_t microbit_panic(mp_uint_t n_args, const mp_obj_t *args) {
while(true) {
microbit_display_show(&microbit_display_obj, (microbit_image_obj_t*)&panic);
mp_hal_delay_ms(1000);
char num[4];
int code;
if (n_args) {
code = mp_obj_get_int(args[0]);
} else {
code = 0;
}
num[2] = code%10 + '0';
code /= 10;
num[1] = code%10 + '0';
code /= 10;
num[0] = code%10 + '0';
for (int i = 0; i < 3; i++) {
microbit_display_show(&microbit_display_obj, microbit_image_for_char(num[i]));
mp_hal_delay_ms(1000);
}
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_panic_obj, 0, 1, microbit_panic);
STATIC mp_obj_t microbit_temperature(void) {
int temp;
NRF_TEMP->TASKS_START = 1;
while (NRF_TEMP->EVENTS_DATARDY == 0);
NRF_TEMP->EVENTS_DATARDY = 0;
temp = NRF_TEMP->TEMP;
NRF_TEMP->TASKS_STOP = 1;
return mp_obj_new_float(temp/4.0);
}
MP_DEFINE_CONST_FUN_OBJ_0(microbit_temperature_obj, microbit_temperature);
STATIC const mp_map_elem_t microbit_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_microbit) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Image), (mp_obj_t)&microbit_image_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_display), (mp_obj_t)&microbit_display_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_button_a), (mp_obj_t)&microbit_button_a_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_button_b), (mp_obj_t)&microbit_button_b_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_accelerometer), (mp_obj_t)&microbit_accelerometer_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_compass), (mp_obj_t)&microbit_compass_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_i2c), (mp_obj_t)&microbit_i2c_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_uart), (mp_obj_t)&microbit_uart_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_spi), (mp_obj_t)&microbit_spi_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&microbit_reset_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&microbit_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_running_time), (mp_obj_t)&microbit_running_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_panic), (mp_obj_t)&microbit_panic_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_temperature), (mp_obj_t)&microbit_temperature_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin0), (mp_obj_t)&microbit_p0_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin1), (mp_obj_t)&microbit_p1_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin2), (mp_obj_t)&microbit_p2_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin3), (mp_obj_t)&microbit_p3_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin4), (mp_obj_t)&microbit_p4_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin5), (mp_obj_t)&microbit_p5_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin6), (mp_obj_t)&microbit_p6_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin7), (mp_obj_t)&microbit_p7_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin8), (mp_obj_t)&microbit_p8_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin9), (mp_obj_t)&microbit_p9_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin10), (mp_obj_t)&microbit_p10_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin11), (mp_obj_t)&microbit_p11_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin12), (mp_obj_t)&microbit_p12_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin13), (mp_obj_t)&microbit_p13_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin14), (mp_obj_t)&microbit_p14_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin15), (mp_obj_t)&microbit_p15_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin16), (mp_obj_t)&microbit_p16_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin19), (mp_obj_t)&microbit_p19_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin20), (mp_obj_t)&microbit_p20_obj },
};
STATIC MP_DEFINE_CONST_DICT(microbit_module_globals, microbit_module_globals_table);
const mp_obj_module_t microbit_module = {
.base = { &mp_type_module },
.name = MP_QSTR_microbit,
.globals = (mp_obj_dict_t*)&microbit_module_globals,
};
}

View File

@ -0,0 +1,234 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_MICROBIT_MODMICROBIT_H__
#define __MICROPY_INCLUDED_MICROBIT_MODMICROBIT_H__
#include "py/objtuple.h"
extern const mp_obj_type_t microbit_ad_pin_type;
extern const mp_obj_type_t microbit_dig_pin_type;
extern const mp_obj_type_t microbit_touch_pin_type;
extern const struct _microbit_pin_obj_t microbit_p0_obj;
extern const struct _microbit_pin_obj_t microbit_p1_obj;
extern const struct _microbit_pin_obj_t microbit_p2_obj;
extern const struct _microbit_pin_obj_t microbit_p3_obj;
extern const struct _microbit_pin_obj_t microbit_p4_obj;
extern const struct _microbit_pin_obj_t microbit_p5_obj;
extern const struct _microbit_pin_obj_t microbit_p6_obj;
extern const struct _microbit_pin_obj_t microbit_p7_obj;
extern const struct _microbit_pin_obj_t microbit_p8_obj;
extern const struct _microbit_pin_obj_t microbit_p9_obj;
extern const struct _microbit_pin_obj_t microbit_p10_obj;
extern const struct _microbit_pin_obj_t microbit_p11_obj;
extern const struct _microbit_pin_obj_t microbit_p12_obj;
extern const struct _microbit_pin_obj_t microbit_p13_obj;
extern const struct _microbit_pin_obj_t microbit_p14_obj;
extern const struct _microbit_pin_obj_t microbit_p15_obj;
extern const struct _microbit_pin_obj_t microbit_p16_obj;
extern const struct _microbit_pin_obj_t microbit_p19_obj;
extern const struct _microbit_pin_obj_t microbit_p20_obj;
extern const mp_obj_type_t microbit_const_image_type;
extern const struct _monochrome_5by5_t microbit_const_image_heart_obj;
extern const struct _monochrome_5by5_t microbit_const_image_heart_small_obj;
extern const struct _monochrome_5by5_t microbit_const_image_happy_obj;
extern const struct _monochrome_5by5_t microbit_const_image_smile_obj;
extern const struct _monochrome_5by5_t microbit_const_image_sad_obj;
extern const struct _monochrome_5by5_t microbit_const_image_confused_obj;
extern const struct _monochrome_5by5_t microbit_const_image_angry_obj;
extern const struct _monochrome_5by5_t microbit_const_image_asleep_obj;
extern const struct _monochrome_5by5_t microbit_const_image_surprised_obj;
extern const struct _monochrome_5by5_t microbit_const_image_silly_obj;
extern const struct _monochrome_5by5_t microbit_const_image_fabulous_obj;
extern const struct _monochrome_5by5_t microbit_const_image_meh_obj;
extern const struct _monochrome_5by5_t microbit_const_image_yes_obj;
extern const struct _monochrome_5by5_t microbit_const_image_no_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock12_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock1_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock2_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock3_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock4_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock5_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock6_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock7_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock8_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock9_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock10_obj;
extern const struct _monochrome_5by5_t microbit_const_image_clock11_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_n_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_ne_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_e_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_se_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_s_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_sw_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_w_obj;
extern const struct _monochrome_5by5_t microbit_const_image_arrow_nw_obj;
extern const struct _monochrome_5by5_t microbit_const_image_triangle_obj;
extern const struct _monochrome_5by5_t microbit_const_image_triangle_left_obj;
extern const struct _monochrome_5by5_t microbit_const_image_chessboard_obj;
extern const struct _monochrome_5by5_t microbit_const_image_diamond_obj;
extern const struct _monochrome_5by5_t microbit_const_image_diamond_small_obj;
extern const struct _monochrome_5by5_t microbit_const_image_square_obj;
extern const struct _monochrome_5by5_t microbit_const_image_square_small_obj;
extern const struct _monochrome_5by5_t microbit_const_image_rabbit;
extern const struct _monochrome_5by5_t microbit_const_image_cow;
extern const struct _monochrome_5by5_t microbit_const_image_music_crotchet_obj;
extern const struct _monochrome_5by5_t microbit_const_image_music_quaver_obj;
extern const struct _monochrome_5by5_t microbit_const_image_music_quavers_obj;
extern const struct _monochrome_5by5_t microbit_const_image_pitchfork_obj;
extern const struct _monochrome_5by5_t microbit_const_image_xmas_obj;
extern const struct _monochrome_5by5_t microbit_const_image_pacman_obj;
extern const struct _monochrome_5by5_t microbit_const_image_target_obj;
extern const struct _mp_obj_tuple_t microbit_const_image_all_clocks_tuple_obj;
extern const struct _mp_obj_tuple_t microbit_const_image_all_arrows_tuple_obj;
extern const struct _monochrome_5by5_t microbit_const_image_tshirt_obj;
extern const struct _monochrome_5by5_t microbit_const_image_rollerskate_obj;
extern const struct _monochrome_5by5_t microbit_const_image_duck_obj;
extern const struct _monochrome_5by5_t microbit_const_image_house_obj;
extern const struct _monochrome_5by5_t microbit_const_image_tortoise_obj;
extern const struct _monochrome_5by5_t microbit_const_image_butterfly_obj;
extern const struct _monochrome_5by5_t microbit_const_image_stickfigure_obj;
extern const struct _monochrome_5by5_t microbit_const_image_ghost_obj;
extern const struct _monochrome_5by5_t microbit_const_image_sword_obj;
extern const struct _monochrome_5by5_t microbit_const_image_giraffe_obj;
extern const struct _monochrome_5by5_t microbit_const_image_skull_obj;
extern const struct _monochrome_5by5_t microbit_const_image_umbrella_obj;
extern const struct _monochrome_5by5_t microbit_const_image_snake_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_dadadadum_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_entertainer_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_prelude_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_ode_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_nyan_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_ringtone_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_funk_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_blues_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_birthday_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_wedding_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_funeral_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_punchline_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_python_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_baddy_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_chase_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_ba_ding_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_wawawawaa_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_jump_up_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_jump_down_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_power_up_obj;
extern const struct _mp_obj_tuple_t microbit_music_tune_power_down_obj;
extern const mp_obj_type_t microbit_image_type;
extern const mp_obj_type_t microbit_accelerometer_type;
extern const struct _microbit_accelerometer_obj_t microbit_accelerometer_obj;
extern struct _microbit_display_obj_t microbit_display_obj;
extern const struct _microbit_button_obj_t microbit_button_a_obj;
extern const struct _microbit_button_obj_t microbit_button_b_obj;
extern const struct _microbit_compass_obj_t microbit_compass_obj;
extern const struct _microbit_i2c_obj_t microbit_i2c_obj;
extern struct _microbit_uart_obj_t microbit_uart_obj;
extern struct _microbit_spi_obj_t microbit_spi_obj;
MP_DECLARE_CONST_FUN_OBJ(microbit_reset_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_sleep_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_random_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_running_time_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_temperature_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_panic_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_accelerometer_get_x_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_accelerometer_get_y_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_accelerometer_get_z_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_button_is_pressed_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_button_was_pressed_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_button_get_presses_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_is_calibrated_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_heading_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_calibrate_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_is_calibrating_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_clear_calibration_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_get_x_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_get_y_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_get_z_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_compass_get_field_strength_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_show_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_scroll_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_clear_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_get_pixel_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_set_pixel_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_on_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_off_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_display_is_on_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_read_digital_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_write_digital_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_read_analog_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_write_analog_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_is_touched_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_set_analog_period_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_pin_set_analog_period_microseconds_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_i2c_init_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_i2c_read_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_i2c_write_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_width_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_height_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_get_pixel_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_set_pixel_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_shift_left_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_shift_right_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_shift_up_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_shift_down_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_copy_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_crop_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_invert_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_image_slice_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_uart_init_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_uart_any_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_read_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_readall_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readline_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_readinto_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_write_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_spi_init_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_spi_write_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_spi_read_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_spi_write_readinto_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_music_set_tempo_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_music_pitch_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_music_play_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_music_get_tempo_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_music_stop_obj);
MP_DECLARE_CONST_FUN_OBJ(microbit_music_reset_obj);
MP_DECLARE_CONST_FUN_OBJ(love_badaboom_obj);
MP_DECLARE_CONST_FUN_OBJ(this_authors_obj);
extern const mp_obj_module_t microbit_module;
extern const mp_obj_module_t music_module;
extern const mp_obj_module_t love_module;
extern const mp_obj_module_t antigravity_module;
extern const mp_obj_module_t this_module;
#endif // __MICROPY_INCLUDED_MICROBIT_MODMICROBIT_H__