head	1.2;
access;
symbols
	micropython-1-5-2-base:1.1.1.1 MICROPYTHON:1.1.1;
locks; strict;
comment	@ * @;


1.2
date	2026.10.15.05.29.18;	author agc;	state dead;
branches;
next	1.1;
commitid	aHLdC1EGCUYk7xZG;

1.1
date	2016.01.14.01.38.51;	author agc;	state Exp;
branches
	1.1.1.1;
next	;
commitid	Q8liT0v6zMF95QQy;

1.1.1.1
date	2016.01.14.01.38.51;	author agc;	state Exp;
branches;
next	;
commitid	Q8liT0v6zMF95QQy;


desc
@@


1.2
log
@Remove waaaay old micropython sources which haven't been relevant for 10 years
@
text
@#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_raise(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.0F) {
        angle = 0.0F;
    }
    if (angle > 180.0F) {
        angle = 180.0F;
    }
    servo_ticks[self->servo_id] = map_float_to_uint(angle,
                                                    0.0F, 180.0F,
                                                    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, mp_print_kind_t kind) {
    pyb_servo_obj_t *self = self_in;
    (void)kind;
    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_type_type },
    .name = MP_QSTR_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_raise(mp_obj_new_exception_msg(&mp_type_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
	if (servo_active_mask & (1 << channel_high)) {
		digitalWrite(servo_pin[channel_high], LOW);
		channel_high = MAX_SERVOS;
	}
	// search for the next channel to turn on
	while (channel < MAX_SERVOS) {
		if (servo_active_mask & (1 << channel)) {
			digitalWrite(servo_pin[channel], HIGH);
			channel_high = channel;
			ticks = servo_ticks[channel];
			tick_accum += ticks;
			PDB0_IDLY += ticks;
			PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
			channel++;
			return;
		}
		channel++;
	}
	// when all channels have output, wait for the
	// minimum refresh interval
	wait_ticks = usToTicks(REFRESH_INTERVAL) - tick_accum;
	if (wait_ticks < usToTicks(100)) wait_ticks = usToTicks(100);
	else if (wait_ticks > 60000) wait_ticks = 60000;
	tick_accum += wait_ticks;
	PDB0_IDLY += wait_ticks;
	PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
	// if this wait is enough to satisfy the refresh
	// interval, next time begin again at channel zero
	if (tick_accum >= usToTicks(REFRESH_INTERVAL)) {
		tick_accum = 0;
		channel = 0;
	}
}
@


1.1
log
@Initial revision
@
text
@@


1.1.1.1
log
@Import micropython version 1.5.2 into othersrc.

Micropython is a python3 implementation that has been optimised for
micro-controllers and small embedded systems.  It also has a "unix"
port. It has an MIT license.

This is version 1.5.2 of micropython.

	MicroPython implements the entire Python 3.4 syntax (including
	exceptions, "with", "yield from", etc.).  The following core
	datatypes are provided:  str (including basic Unicode
	support), bytes, bytearray, tuple, list, dict, set, frozenset,
	array.array, collections.namedtuple, classes and instances. 
	Builtin modules include sys, time, and struct.  Note that only
	subset of Python 3.4 functionality implemented for the data
	types and modules.

This is the standard micropython source (version v1.5.2), which has been
adapted to use reachover infrastructure. At the present time, libffi
(from pkgsrc) is used. Alternative locations for libffi can be set
using the PKGSRC_PREFIX definition to make.

In the whole scheme of things, micropython is quite small:

	% size bin/micropython
	   text    data     bss     dec     hex filename
	 393495    1624    2208  397327   6100f bin/micropython
	%

and runs much as expected:

	% bin/micropython
	MicroPython v1.5.2 on 2016-01-13; linux version
	Use Ctrl-D to exit, Ctrl-E for paste mode
	>>> print("hello world")
	hello world
	>>> list(5 * x + y for x in range(10) for y in [4, 2, 1])
	[4, 2, 1, 9, 7, 6, 14, 12, 11, 19, 17, 16, 24, 22, 21, 29, 27, 26, 34, 32, 31, 39, 37, 36, 44, 42, 41, 49, 47, 46]
	>>>
	% python2.7
	Python 2.7.10 (default, Oct 17 2015, 17:55:29)
	[GCC 4.8.5] on netbsd7
	Type "help", "copyright", "credits" or "license" for more information.
	>>> print("hello world")
	hello world
	>>> list(5 * x + y for x in range(10) for y in [4, 2, 1])
	[4, 2, 1, 9, 7, 6, 14, 12, 11, 19, 17, 16, 24, 22, 21, 29, 27, 26, 34, 32, 31, 39, 37, 36, 44, 42, 41, 49, 47, 46]
	>>> ^D
	%

This (reachover) version runs all the tests which the gmake version does.

	% make t
	cd bin && make t
	cd /home/agc/local/micropython/bin/../dist/unix/../tests && env MICROPY_MICROPYTHON=/home/agc/local/micropython/bin/micropython ./run-tests
	pass  basics/0prelim.py
	pass  basics/andor.py
	pass  basics/array1.py
	pass  basics/array_add.py
	pass  basics/array_construct.py
	pass  basics/array_construct2.py
	...
	pass  unix/ffi_callback.py
	pass  unix/ffi_float.py
	pass  unix/ffi_float2.py
	474 tests performed (15812 individual testcases)
	474 tests passed
	5 tests skipped: cmd_showbc cmd_verbose machine1 machine_mem extra_coverage
	%

The sources are available from github:
	https://github.com/micropython/micropython

micropython release at:
	https://github.com/micropython/micropython/releases

Sources for 1.5.2 taken from:
	https://github.com/micropython/micropython/archive/v1.5.2.tar.gz

Alistair Crooks
agc@@netbsd.org
Wed Jan 13 17:15:30 PST 2016
@
text
@@
