Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
724026ab
Commit
724026ab
authored
Feb 10, 2014
by
Damien George
Browse files
Merge pull request #271 from dhylands/teensy-2014-02-10
Updated teensy to work with latest on master
parents
b0b7518d
6f9c0367
Changes
9
Hide whitespace changes
Inline
Side-by-side
teensy/Makefile
View file @
724026ab
include
../py/mkenv.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS
=
qstrdefsport.h
# include py core make definitions
include
../py/py.mk
...
...
@@ -32,6 +35,8 @@ SRC_C = \
lexerfatfs.c
\
lexermemzip.c
\
memzip.c
\
servo.c
\
usart.c
\
usb.c
\
STM_SRC_C
=
$(
addprefix
stm/,
\
...
...
@@ -54,7 +59,7 @@ SRC_TEENSY = \
usb_serial.c
\
yield.c
\
OBJ
=
$(
addprefix
$(BUILD)
/,
$(SRC_C:.c=.o)
$(STM_SRC_C:.c=.o)
$(STM_SRC_S:.s=.o)
$(SRC_TEENSY:.c=.o)
)
$(PY_O)
OBJ
=
$(PY_O)
$(
addprefix
$(BUILD)
/,
$(SRC_C:.c=.o)
$(STM_SRC_C:.c=.o)
$(STM_SRC_S:.s=.o)
$(SRC_TEENSY:.c=.o)
)
#LIB = -lreadline
# the following is needed for BSD
#LIB += -ltermcap
...
...
teensy/led.c
View file @
724026ab
...
...
@@ -2,6 +2,7 @@
#include
"misc.h"
#include
"mpconfig.h"
#include
"qstr.h"
#include
"obj.h"
#include
"led.h"
...
...
teensy/lexerfatfs.c
View file @
724026ab
...
...
@@ -2,11 +2,13 @@
#include
<stdio.h>
#include
"misc.h"
#include
"mpconfig.h"
#include
"qstr.h"
#include
"lexer.h"
typedef
int
FIL
;
#include
"../stm/lexerfatfs.h"
mp_lexer_t
*
mp_lexer_new_from_file
(
const
char
*
filename
,
mp_lexer_file_buf_t
*
fb
)
{
mp_lexer_t
*
mp_lexer_new_from_file
(
const
char
*
filename
)
{
printf
(
"import not implemented
\n
"
);
return
NULL
;
}
...
...
@@ -15,3 +17,8 @@ mp_lexer_t *mp_import_open_file(qstr mod_name) {
printf
(
"import not implemented
\n
"
);
return
NULL
;
}
mp_import_stat_t
mp_import_stat
(
const
char
*
path
)
{
// TODO implement me!
return
MP_IMPORT_STAT_NO_EXIST
;
}
teensy/lexermemzip.c
View file @
724026ab
...
...
@@ -2,6 +2,8 @@
#include
<stdlib.h>
#include
"misc.h"
#include
"mpconfig.h"
#include
"qstr.h"
#include
"lexer.h"
#include
"memzip.h"
...
...
@@ -13,6 +15,7 @@ mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename)
if
(
memzip_locate
(
filename
,
&
data
,
&
len
)
!=
MZ_OK
)
{
return
NULL
;
}
return
mp_lexer_new_from_str_len
(
filename
,
(
const
char
*
)
data
,
(
uint
)
len
,
0
);
return
mp_lexer_new_from_str_len
(
qstr_from_str
(
filename
),
(
const
char
*
)
data
,
(
uint
)
len
,
0
);
}
teensy/main.c
View file @
724026ab
...
...
@@ -6,7 +6,7 @@
#include
"nlr.h"
#include
"misc.h"
#include
"mpconfig.h"
#include
"
mp
qstr.h"
#include
"qstr.h"
#include
"lexer.h"
#include
"lexermemzip.h"
#include
"parse.h"
...
...
@@ -15,6 +15,7 @@
#include
"runtime0.h"
#include
"runtime.h"
#include
"repl.h"
#include
"servo.h"
#include
"usb.h"
#include
"gc.h"
#include
"led.h"
...
...
@@ -54,6 +55,32 @@ static const char *help_text =
#endif
;
mp_obj_t
pyb_analog_read
(
mp_obj_t
pin_obj
)
{
uint
pin
=
mp_obj_get_int
(
pin_obj
);
int
val
=
analogRead
(
pin
);
return
MP_OBJ_NEW_SMALL_INT
(
val
);
}
mp_obj_t
pyb_analog_write
(
mp_obj_t
pin_obj
,
mp_obj_t
val_obj
)
{
uint
pin
=
mp_obj_get_int
(
pin_obj
);
int
val
=
mp_obj_get_int
(
val_obj
);
analogWrite
(
pin
,
val
);
return
mp_const_none
;
}
mp_obj_t
pyb_analog_write_resolution
(
mp_obj_t
res_obj
)
{
int
res
=
mp_obj_get_int
(
res_obj
);
analogWriteResolution
(
res
);
return
mp_const_none
;
}
mp_obj_t
pyb_analog_write_frequency
(
mp_obj_t
pin_obj
,
mp_obj_t
freq_obj
)
{
uint
pin
=
mp_obj_get_int
(
pin_obj
);
int
freq
=
mp_obj_get_int
(
freq_obj
);
analogWriteFrequency
(
pin
,
freq
);
return
mp_const_none
;
}
// get some help about available functions
static
mp_obj_t
pyb_help
(
void
)
{
printf
(
"%s"
,
help_text
);
...
...
@@ -181,16 +208,26 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
}
#endif
static
qstr
pyb_config_source_dir
=
0
;
static
qstr
pyb_config_main
=
0
;
static
mp_obj_t
pyb_config_source_dir
=
MP_OBJ_NULL
;
static
mp_obj_t
pyb_config_main
=
MP_OBJ_NULL
;
mp_obj_t
pyb_source_dir
(
mp_obj_t
source_dir
)
{
pyb_config_source_dir
=
mp_obj_get_qstr
(
source_dir
);
if
(
MP_OBJ_IS_STR
(
source_dir
))
{
pyb_config_source_dir
=
source_dir
;
printf
(
"source_dir = '"
);
mp_obj_print
(
source_dir
,
PRINT_STR
);
printf
(
"'
\n
"
);
}
return
mp_const_none
;
}
mp_obj_t
pyb_main
(
mp_obj_t
main
)
{
pyb_config_main
=
mp_obj_get_qstr
(
main
);
if
(
MP_OBJ_IS_STR
(
main
))
{
pyb_config_main
=
main
;
printf
(
"main = '"
);
mp_obj_print
(
main
,
PRINT_STR
);
printf
(
"'
\n
"
);
}
return
mp_const_none
;
}
...
...
@@ -205,7 +242,7 @@ mp_obj_t pyb_led(mp_obj_t state) {
}
mp_obj_t
pyb_run
(
mp_obj_t
filename_obj
)
{
const
char
*
filename
=
qstr_str
(
mp_obj_get_qstr
(
filename_obj
));
const
char
*
filename
=
qstr_str
(
mp_obj_
str_
get_qstr
(
filename_obj
));
do_file
(
filename
);
return
mp_const_none
;
}
...
...
@@ -309,15 +346,24 @@ bool do_file(const char *filename) {
return
false
;
}
mp_parse_node_t
pn
=
mp_parse
(
lex
,
MP_PARSE_FILE_INPUT
);
qstr
parse_exc_id
;
const
char
*
parse_exc_msg
;
mp_parse_node_t
pn
=
mp_parse
(
lex
,
MP_PARSE_FILE_INPUT
,
&
parse_exc_id
,
&
parse_exc_msg
);
qstr
source_name
=
mp_lexer_source_name
(
lex
);
mp_lexer_free
(
lex
);
if
(
pn
==
MP_PARSE_NODE_NULL
)
{
// parse error
mp_lexer_show_error_pythonic_prefix
(
lex
);
printf
(
"%s: %s
\n
"
,
qstr_str
(
parse_exc_id
),
parse_exc_msg
);
mp_lexer_free
(
lex
);
return
false
;
}
mp_lexer_free
(
lex
);
mp_obj_t
module_fun
=
mp_compile
(
pn
,
source_name
,
false
);
mp_parse_node_free
(
pn
);
if
(
module_fun
==
mp_const_none
)
{
return
false
;
}
...
...
@@ -329,7 +375,7 @@ bool do_file(const char *filename) {
return
true
;
}
else
{
// uncaught exception
mp_obj_print
((
mp_obj_t
)
nlr
.
ret_val
);
mp_obj_print
((
mp_obj_t
)
nlr
.
ret_val
,
PRINT_REPR
);
printf
(
"
\n
"
);
return
false
;
}
...
...
@@ -340,7 +386,7 @@ void do_repl(void) {
stdout_tx_str
(
"Type
\"
help()
\"
for more information.
\r\n
"
);
vstr_t
line
;
vstr_init
(
&
line
);
vstr_init
(
&
line
,
32
);
for
(;;)
{
vstr_reset
(
&
line
);
...
...
@@ -366,12 +412,21 @@ void do_repl(void) {
}
}
mp_lexer_t
*
lex
=
mp_lexer_new_from_str_len
(
"<stdin>"
,
vstr_str
(
&
line
),
vstr_len
(
&
line
),
0
);
mp_parse_node_t
pn
=
mp_parse
(
lex
,
MP_PARSE_SINGLE_INPUT
);
mp_lexer_free
(
lex
);
if
(
pn
!=
MP_PARSE_NODE_NULL
)
{
mp_obj_t
module_fun
=
mp_compile
(
pn
,
true
);
mp_lexer_t
*
lex
=
mp_lexer_new_from_str_len
(
MP_QSTR__lt_stdin_gt_
,
vstr_str
(
&
line
),
vstr_len
(
&
line
),
0
);
qstr
parse_exc_id
;
const
char
*
parse_exc_msg
;
mp_parse_node_t
pn
=
mp_parse
(
lex
,
MP_PARSE_SINGLE_INPUT
,
&
parse_exc_id
,
&
parse_exc_msg
);
qstr
source_name
=
mp_lexer_source_name
(
lex
);
if
(
pn
==
MP_PARSE_NODE_NULL
)
{
// parse error
mp_lexer_show_error_pythonic_prefix
(
lex
);
printf
(
"%s: %s
\n
"
,
qstr_str
(
parse_exc_id
),
parse_exc_msg
);
mp_lexer_free
(
lex
);
}
else
{
// parse okay
mp_lexer_free
(
lex
);
mp_obj_t
module_fun
=
mp_compile
(
pn
,
source_name
,
true
);
if
(
module_fun
!=
mp_const_none
)
{
nlr_buf_t
nlr
;
uint32_t
start
=
micros
();
...
...
@@ -381,11 +436,11 @@ void do_repl(void) {
// optional timing
if
(
0
)
{
uint32_t
ticks
=
micros
()
-
start
;
// TODO implement a function that does this properly
printf
(
"(took %lu
u
s)
\n
"
,
ticks
);
printf
(
"(took %lu
m
s)
\n
"
,
ticks
);
}
}
else
{
// uncaught exception
mp_obj_print
((
mp_obj_t
)
nlr
.
ret_val
);
mp_obj_print
((
mp_obj_t
)
nlr
.
ret_val
,
PRINT_REPR
);
printf
(
"
\n
"
);
}
}
...
...
@@ -396,11 +451,15 @@ void do_repl(void) {
}
int
main
(
void
)
{
pinMode
(
LED_BUILTIN
,
OUTPUT
);
pinMode
(
LED_BUILTIN
,
OUTPUT
);
#if 0
// Wait for host side to get connected
while (!usb_vcp_is_connected()) {
;
}
#else
delay
(
1000
);
#endif
led_init
();
led_state
(
PYB_LED_BUILTIN
,
1
);
...
...
@@ -415,28 +474,34 @@ soft_reset:
qstr_init
();
rt_init
();
#if 1
// add some functions to the python namespace
{
rt_store_name
(
qstr_from_str_static
(
"help"
),
rt_make_function_0
(
pyb_help
));
mp_obj_t
m
=
mp_obj_new_module
(
qstr_from_str_static
(
"pyb"
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"info"
),
rt_make_function_0
(
pyb_info
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"source_dir"
),
rt_make_function_1
(
pyb_source_dir
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"main"
),
rt_make_function_1
(
pyb_main
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"gc"
),
rt_make_function_0
(
pyb_gc
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"delay"
),
rt_make_function_1
(
pyb_delay
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"led"
),
rt_make_function_1
(
pyb_led
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"Led"
),
rt_make_function_1
(
pyb_Led
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"gpio"
),
(
mp_obj_t
)
&
pyb_gpio_obj
);
rt_store_name
(
qstr_from_str_static
(
"pyb"
),
m
);
rt_store_name
(
qstr_from_str_static
(
"run"
),
rt_make_function_1
(
pyb_run
));
rt_store_name
(
MP_QSTR_help
,
rt_make_function_n
(
0
,
pyb_help
));
mp_obj_t
m
=
mp_obj_new_module
(
MP_QSTR_pyb
);
rt_store_attr
(
m
,
MP_QSTR_info
,
rt_make_function_n
(
0
,
pyb_info
));
rt_store_attr
(
m
,
MP_QSTR_source_dir
,
rt_make_function_n
(
1
,
pyb_source_dir
));
rt_store_attr
(
m
,
MP_QSTR_main
,
rt_make_function_n
(
1
,
pyb_main
));
rt_store_attr
(
m
,
MP_QSTR_gc
,
rt_make_function_n
(
0
,
pyb_gc
));
rt_store_attr
(
m
,
MP_QSTR_delay
,
rt_make_function_n
(
1
,
pyb_delay
));
rt_store_attr
(
m
,
MP_QSTR_led
,
rt_make_function_n
(
1
,
pyb_led
));
rt_store_attr
(
m
,
MP_QSTR_Led
,
rt_make_function_n
(
1
,
pyb_Led
));
rt_store_attr
(
m
,
MP_QSTR_analogRead
,
rt_make_function_n
(
1
,
pyb_analog_read
));
rt_store_attr
(
m
,
MP_QSTR_analogWrite
,
rt_make_function_n
(
2
,
pyb_analog_write
));
rt_store_attr
(
m
,
MP_QSTR_analogWriteResolution
,
rt_make_function_n
(
1
,
pyb_analog_write_resolution
));
rt_store_attr
(
m
,
MP_QSTR_analogWriteFrequency
,
rt_make_function_n
(
2
,
pyb_analog_write_frequency
));
rt_store_attr
(
m
,
MP_QSTR_gpio
,
(
mp_obj_t
)
&
pyb_gpio_obj
);
rt_store_attr
(
m
,
MP_QSTR_Servo
,
rt_make_function_n
(
0
,
pyb_Servo
));
rt_store_name
(
MP_QSTR_pyb
,
m
);
rt_store_name
(
MP_QSTR_run
,
rt_make_function_n
(
1
,
pyb_run
));
}
#endif
printf
(
"About execute /boot.py
\n
"
);
if
(
!
do_file
(
"/boot.py"
))
{
printf
(
"Unable to open '/boot.py'
\n
"
);
flash_error
(
4
);
}
printf
(
"Done executing /boot.py
\n
"
);
// Turn bootup LED off
led_state
(
PYB_LED_BUILTIN
,
0
);
...
...
@@ -445,21 +510,23 @@ soft_reset:
{
vstr_t
*
vstr
=
vstr_new
();
vstr_add_str
(
vstr
,
"/"
);
if
(
pyb_config_source_dir
==
0
)
{
if
(
pyb_config_source_dir
==
MP_OBJ_NULL
)
{
vstr_add_str
(
vstr
,
"src"
);
}
else
{
vstr_add_str
(
vstr
,
qstr
_str
(
pyb_config_source_dir
));
vstr_add_str
(
vstr
,
mp_obj_str_get
_str
(
pyb_config_source_dir
));
}
vstr_add_char
(
vstr
,
'/'
);
if
(
pyb_config_main
==
0
)
{
if
(
pyb_config_main
==
MP_OBJ_NULL
)
{
vstr_add_str
(
vstr
,
"main.py"
);
}
else
{
vstr_add_str
(
vstr
,
qstr
_str
(
pyb_config_main
));
vstr_add_str
(
vstr
,
mp_obj_str_get
_str
(
pyb_config_main
));
}
printf
(
"About execute '%s'
\n
"
,
vstr_str
(
vstr
));
if
(
!
do_file
(
vstr_str
(
vstr
)))
{
printf
(
"Unable to open '%s'
\n
"
,
vstr_str
(
vstr
));
flash_error
(
3
);
}
printf
(
"Done executing '%s'
\n
"
,
vstr_str
(
vstr
));
vstr_free
(
vstr
);
}
...
...
@@ -471,16 +538,6 @@ soft_reset:
goto
soft_reset
;
}
double
__aeabi_f2d
(
float
x
)
{
// TODO
return
0
.
0
;
}
float
__aeabi_d2f
(
double
x
)
{
// TODO
return
0
.
0
;
}
double
sqrt
(
double
x
)
{
// TODO
return
0
.
0
;
...
...
teensy/qstrdefsport.h
0 → 100644
View file @
724026ab
// qstrs specific to this port
Q
(
help
)
Q
(
pyb
)
Q
(
info
)
Q
(
sd_test
)
Q
(
stop
)
Q
(
standby
)
Q
(
source_dir
)
Q
(
main
)
Q
(
sync
)
Q
(
gc
)
Q
(
delay
)
Q
(
switch
)
Q
(
servo
)
Q
(
pwm
)
Q
(
accel
)
Q
(
mma_read
)
Q
(
mma_mode
)
Q
(
hid
)
Q
(
time
)
Q
(
rand
)
Q
(
Led
)
Q
(
led
)
Q
(
Servo
)
Q
(
I2C
)
Q
(
gpio
)
Q
(
Usart
)
Q
(
ADC
)
Q
(
open
)
Q
(
analogRead
)
Q
(
analogWrite
)
Q
(
analogWriteResolution
)
Q
(
analogWriteFrequency
)
Q
(
run
)
teensy/servo.c
0 → 100644
View file @
724026ab
#include
<stdio.h>
#include
"misc.h"
#include
"mpconfig.h"
#include
"qstr.h"
#include
"nlr.h"
#include
"obj.h"
#include
"servo.h"
#include
"Arduino.h"
#define MAX_SERVOS 12
#define INVALID_SERVO -1
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
#define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE \
| PDB_SC_CONT | PDB_SC_PRESCALER(2) | PDB_SC_MULT(0))
#define PDB_PRESCALE 4
#define usToTicks(us) ((us) * (F_BUS / 1000) / PDB_PRESCALE / 1000)
#define ticksToUs(ticks) ((ticks) * PDB_PRESCALE * 1000 / (F_BUS / 1000))
static
uint16_t
servo_active_mask
=
0
;
static
uint16_t
servo_allocated_mask
=
0
;
static
uint8_t
servo_pin
[
MAX_SERVOS
];
static
uint16_t
servo_ticks
[
MAX_SERVOS
];
typedef
struct
_pyb_servo_obj_t
{
mp_obj_base_t
base
;
uint
servo_id
;
uint
min_usecs
;
uint
max_usecs
;
}
pyb_servo_obj_t
;
#define clamp(v, min_val, max_val) ((v) < (min_val) ? (min_val) : (v) > (max_val) ? (max_val) : (v))
static
float
map_uint_to_float
(
uint
x
,
uint
in_min
,
uint
in_max
,
float
out_min
,
float
out_max
)
{
return
(
float
)(
x
-
in_min
)
*
(
out_max
-
out_min
)
/
(
float
)(
in_max
-
in_min
)
+
(
float
)
out_min
;
}
static
uint
map_float_to_uint
(
float
x
,
float
in_min
,
float
in_max
,
uint
out_min
,
uint
out_max
)
{
return
(
int
)((
x
-
in_min
)
*
(
float
)(
out_max
-
out_min
)
/
(
in_max
-
in_min
)
+
(
float
)
out_min
);
}
static
mp_obj_t
servo_obj_attach
(
mp_obj_t
self_in
,
mp_obj_t
pin_obj
)
{
pyb_servo_obj_t
*
self
=
self_in
;
uint
pin
=
mp_obj_get_int
(
pin_obj
);
if
(
pin
>
CORE_NUM_DIGITAL
)
{
goto
pin_error
;
}
pinMode
(
pin
,
OUTPUT
);
servo_pin
[
self
->
servo_id
]
=
pin
;
servo_active_mask
|=
(
1
<<
self
->
servo_id
);
if
(
!
(
SIM_SCGC6
&
SIM_SCGC6_PDB
))
{
SIM_SCGC6
|=
SIM_SCGC6_PDB
;
// TODO: use bitband for atomic bitset
PDB0_MOD
=
0xFFFF
;
PDB0_CNT
=
0
;
PDB0_IDLY
=
0
;
PDB0_SC
=
PDB_CONFIG
;
// TODO: maybe this should be a higher priority than most
// other interrupts (init all to some default?)
PDB0_SC
=
PDB_CONFIG
|
PDB_SC_SWTRIG
;
}
NVIC_ENABLE_IRQ
(
IRQ_PDB
);
return
mp_const_none
;
pin_error:
nlr_jump
(
mp_obj_new_exception_msg_varg
(
MP_QSTR_ValueError
,
"pin %d does not exist"
,
pin
));
}
static
mp_obj_t
servo_obj_detach
(
mp_obj_t
self_in
)
{
//pyb_servo_obj_t *self = self_in;
return
mp_const_none
;
}
static
mp_obj_t
servo_obj_pin
(
mp_obj_t
self_in
)
{
pyb_servo_obj_t
*
self
=
self_in
;
return
MP_OBJ_NEW_SMALL_INT
(
servo_pin
[
self
->
servo_id
]);
}
static
mp_obj_t
servo_obj_min_usecs
(
int
n_args
,
const
mp_obj_t
*
args
)
{
pyb_servo_obj_t
*
self
=
args
[
0
];
if
(
n_args
==
1
)
{
// get min
return
MP_OBJ_NEW_SMALL_INT
(
self
->
min_usecs
);
}
// Set min
self
->
min_usecs
=
mp_obj_get_int
(
args
[
1
]);
return
mp_const_none
;
}
static
mp_obj_t
servo_obj_max_usecs
(
int
n_args
,
const
mp_obj_t
*
args
)
{
pyb_servo_obj_t
*
self
=
args
[
0
];
if
(
n_args
==
1
)
{
// get max
return
MP_OBJ_NEW_SMALL_INT
(
self
->
max_usecs
);
}
// Set max
self
->
max_usecs
=
mp_obj_get_int
(
args
[
1
]);
return
mp_const_none
;
}
static
mp_obj_t
servo_obj_angle
(
int
n_args
,
const
mp_obj_t
*
args
)
{
pyb_servo_obj_t
*
self
=
args
[
0
];
if
(
n_args
==
1
)
{
// get
float
angle
=
map_uint_to_float
(
servo_ticks
[
self
->
servo_id
],
usToTicks
(
self
->
min_usecs
),
usToTicks
(
self
->
max_usecs
),
0
.
0
,
180
.
0
);
return
mp_obj_new_float
(
angle
);
}
// Set
float
angle
=
mp_obj_get_float
(
args
[
1
]);
if
(
angle
<
0
.
0
F
)
{
angle
=
0
.
0
F
;
}
if
(
angle
>
180
.
0
F
)
{
angle
=
180
.
0
F
;
}
servo_ticks
[
self
->
servo_id
]
=
map_float_to_uint
(
angle
,
0
.
0
F
,
180
.
0
F
,
usToTicks
(
self
->
min_usecs
),
usToTicks
(
self
->
max_usecs
));
return
mp_const_none
;
}
static
mp_obj_t
servo_obj_usecs
(
int
n_args
,
const
mp_obj_t
*
args
)
{
pyb_servo_obj_t
*
self
=
args
[
0
];
uint
usecs
;
if
(
n_args
==
1
)
{
// get
return
MP_OBJ_NEW_SMALL_INT
(
ticksToUs
(
servo_ticks
[
self
->
servo_id
]));
}
// Set
usecs
=
mp_obj_get_int
(
args
[
1
]);
if
(
self
->
min_usecs
<
self
->
max_usecs
)
{
usecs
=
clamp
(
usecs
,
self
->
min_usecs
,
self
->
max_usecs
);
}
else
{
usecs
=
clamp
(
usecs
,
self
->
max_usecs
,
self
->
min_usecs
);
}
servo_ticks
[
self
->
servo_id
]
=
usToTicks
(
usecs
);
return
mp_const_none
;
}
static
mp_obj_t
servo_obj_attached
(
mp_obj_t
self_in
)
{
pyb_servo_obj_t
*
self
=
self_in
;
uint
attached
=
(
servo_active_mask
&
(
1
<<
self
->
servo_id
))
!=
0
;
return
MP_OBJ_NEW_SMALL_INT
(
attached
);
}
static
void
servo_obj_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
)
{
pyb_servo_obj_t
*
self
=
self_in
;
print
(
env
,
"<Servo %lu>"
,
self
->
servo_id
);
}
static
MP_DEFINE_CONST_FUN_OBJ_2
(
servo_obj_attach_obj
,
servo_obj_attach
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
servo_obj_detach_obj
,
servo_obj_detach
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
servo_obj_pin_obj
,
servo_obj_pin
);
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
servo_obj_min_usecs_obj
,
1
,
2
,
servo_obj_min_usecs
);
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
servo_obj_max_usecs_obj
,
1
,
2
,
servo_obj_max_usecs
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
servo_obj_attached_obj
,
servo_obj_attached
);
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
servo_obj_angle_obj
,
1
,
2
,
servo_obj_angle
);
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
servo_obj_usecs_obj
,
1
,
2
,
servo_obj_usecs
);
static
const
mp_method_t
servo_methods
[]
=
{
{
"attach"
,
&
servo_obj_attach_obj
},
{
"detach"
,
&
servo_obj_detach_obj
},
{
"pin"
,
&
servo_obj_pin_obj
},
{
"min_usecs"
,
&
servo_obj_min_usecs_obj
},
{
"max_usecs"
,
&
servo_obj_max_usecs_obj
},
{
"attached"
,
&
servo_obj_attached_obj
},
{
"angle"
,
&
servo_obj_angle_obj
},
{
"usecs"
,
&
servo_obj_usecs_obj
},
{
NULL
,
NULL
},
};
/*
* Notes:
*
* ISR needs to know pin #, ticks
*/
static
const
mp_obj_type_t
servo_obj_type
=
{
{
&
mp_const_type
},
"Servo"
,
.
print
=
servo_obj_print
,
.
methods
=
servo_methods
,
};
/* servo = pyb.Servo(pin, [min_uecs, [max_usecs]]) */
mp_obj_t
pyb_Servo
(
void
)
{
uint16_t
mask
;
pyb_servo_obj_t
*
self
=
m_new_obj
(
pyb_servo_obj_t
);
self
->
base
.
type
=
&
servo_obj_type
;
self
->
min_usecs
=
MIN_PULSE_WIDTH
;
self
->
max_usecs
=
MAX_PULSE_WIDTH
;
/* Find an unallocated servo id */
self
->
servo_id
=
0
;
for
(
mask
=
1
;
mask
<
(
1
<<
MAX_SERVOS
);
mask
<<=
1
)
{
if
(
!
(
servo_allocated_mask
&
mask
))
{
servo_allocated_mask
|=
mask
;
servo_active_mask
&=
~
mask
;
servo_ticks
[
self
->
servo_id
]
=
usToTicks
(
DEFAULT_PULSE_WIDTH
);
return
self
;
}
self
->
servo_id
++
;
}
m_del_obj
(
pyb_servo_obj_t
,
self
);
nlr_jump
(
mp_obj_new_exception_msg
(
MP_QSTR_ValueError
,
"No available servo ids"
));
return
mp_const_none
;
}
void
pdb_isr
(
void
)
{
static
int8_t
channel
=
0
,
channel_high
=
MAX_SERVOS
;
static
uint32_t
tick_accum
=
0
;
uint32_t
ticks
;
int32_t
wait_ticks
;
// first, if any channel was left high from the previous
// run, now is the time to shut it off