Remove traces of TouchDevelop; nicers APIs
This commit is contained in:
Родитель
9dace58eba
Коммит
2f605653d3
7
Makefile
7
Makefile
|
@ -1,9 +1,2 @@
|
|||
SRCCOMMON = source/bitvm.cpp
|
||||
HEADERS = inc/BitVM.h inc/MicroBitTouchDevelop.h
|
||||
|
||||
-include Makefile.local
|
||||
|
||||
all:
|
||||
mkdir -p build
|
||||
node scripts/functionTable.js $(SRCCOMMON) $(HEADERS) yotta_modules/microbit-dal/inc/*.h
|
||||
yotta build
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"microbit" :{
|
||||
"configfile" : "inc/MicroBitCustomConfig.h"
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,219 +0,0 @@
|
|||
(uint32_t)(void*)::bitvm::action::mk, // F3 bvm {shim:action::mk}
|
||||
(uint32_t)(void*)::bitvm::action::run, // P1 bvm {shim:action::run}
|
||||
(uint32_t)(void*)::bitvm::action::run1, // P2 bvm {shim:action::run1}
|
||||
(uint32_t)(void*)::touch_develop::bits::and_uint32, // F2 {shim:bits::and_uint32}
|
||||
(uint32_t)(void*)::bitvm::bitvm_bits::create_buffer, // F1 over {shim:bits::create_buffer}
|
||||
(uint32_t)(void*)::touch_develop::bits::or_uint32, // F2 {shim:bits::or_uint32}
|
||||
(uint32_t)(void*)::touch_develop::bits::rotate_left_uint32, // F2 {shim:bits::rotate_left_uint32}
|
||||
(uint32_t)(void*)::touch_develop::bits::rotate_right_uint32, // F2 {shim:bits::rotate_right_uint32}
|
||||
(uint32_t)(void*)::touch_develop::bits::shift_left_uint32, // F2 {shim:bits::shift_left_uint32}
|
||||
(uint32_t)(void*)::touch_develop::bits::shift_right_uint32, // F2 {shim:bits::shift_right_uint32}
|
||||
(uint32_t)(void*)::touch_develop::bits::xor_uint32, // F2 {shim:bits::xor_uint32}
|
||||
(uint32_t)(void*)::bitvm::allocate, // F1 {shim:bitvm::allocate}
|
||||
(uint32_t)(void*)::bitvm::checkStr, // P2 {shim:bitvm::checkStr}
|
||||
(uint32_t)(void*)::bitvm::const3, // F0 {shim:bitvm::const3}
|
||||
(uint32_t)(void*)::bitvm::debugMemLeaks, // P0 {shim:bitvm::debugMemLeaks}
|
||||
(uint32_t)(void*)::bitvm::decr, // P1 {shim:bitvm::decr}
|
||||
(uint32_t)(void*)::bitvm::error, // P2 {shim:bitvm::error}
|
||||
(uint32_t)(void*)::bitvm::exec_binary, // P1 {shim:bitvm::exec_binary}
|
||||
(uint32_t)(void*)::bitvm::hasVTable, // F1 {shim:bitvm::hasVTable}
|
||||
(uint32_t)(void*)::bitvm::incr, // P1 {shim:bitvm::incr}
|
||||
(uint32_t)(void*)::bitvm::is_invalid, // F1 {shim:bitvm::is_invalid}
|
||||
(uint32_t)(void*)::bitvm::ldfld, // F2 {shim:bitvm::ldfld}
|
||||
(uint32_t)(void*)::bitvm::ldfldRef, // F2 {shim:bitvm::ldfldRef}
|
||||
(uint32_t)(void*)::bitvm::ldglb, // F1 {shim:bitvm::ldglb}
|
||||
(uint32_t)(void*)::bitvm::ldglbRef, // F1 {shim:bitvm::ldglbRef}
|
||||
(uint32_t)(void*)::bitvm::ldloc, // F1 {shim:bitvm::ldloc}
|
||||
(uint32_t)(void*)::bitvm::ldlocRef, // F1 {shim:bitvm::ldlocRef}
|
||||
(uint32_t)(void*)::bitvm::mkStringData, // F1 {shim:bitvm::mkStringData}
|
||||
(uint32_t)(void*)::bitvm::mkloc, // F0 {shim:bitvm::mkloc}
|
||||
(uint32_t)(void*)::bitvm::mklocRef, // F0 {shim:bitvm::mklocRef}
|
||||
(uint32_t)(void*)::bitvm::programHash, // F0 {shim:bitvm::programHash}
|
||||
(uint32_t)(void*)::bitvm::start, // P0 {shim:bitvm::start}
|
||||
(uint32_t)(void*)::bitvm::stclo, // F3 {shim:bitvm::stclo}
|
||||
(uint32_t)(void*)::bitvm::stfld, // P3 {shim:bitvm::stfld}
|
||||
(uint32_t)(void*)::bitvm::stfldRef, // P3 {shim:bitvm::stfldRef}
|
||||
(uint32_t)(void*)::bitvm::stglb, // P2 {shim:bitvm::stglb}
|
||||
(uint32_t)(void*)::bitvm::stglbRef, // P2 {shim:bitvm::stglbRef}
|
||||
(uint32_t)(void*)::bitvm::stloc, // P2 {shim:bitvm::stloc}
|
||||
(uint32_t)(void*)::bitvm::stlocRef, // P2 {shim:bitvm::stlocRef}
|
||||
(uint32_t)(void*)::bitvm::stringData, // F1 {shim:bitvm::stringData}
|
||||
(uint32_t)(void*)::bitvm::templateHash, // F0 {shim:bitvm::templateHash}
|
||||
(uint32_t)(void*)::touch_develop::boolean::and_, // F2 {shim:boolean::and_}
|
||||
(uint32_t)(void*)::touch_develop::boolean::equals, // F2 {shim:boolean::equals}
|
||||
(uint32_t)(void*)::touch_develop::boolean::not_, // F1 {shim:boolean::not_}
|
||||
(uint32_t)(void*)::touch_develop::boolean::or_, // F2 {shim:boolean::or_}
|
||||
(uint32_t)(void*)::bitvm::bitvm_boolean::to_string, // F1 over {shim:boolean::to_string}
|
||||
(uint32_t)(void*)::bitvm::buffer::add, // P2 bvm {shim:buffer::add}
|
||||
(uint32_t)(void*)::bitvm::buffer::at, // F2 bvm {shim:buffer::at}
|
||||
(uint32_t)(void*)::bitvm::buffer::count, // F1 bvm {shim:buffer::count}
|
||||
(uint32_t)(void*)::bitvm::buffer::cptr, // F1 bvm {shim:buffer::cptr}
|
||||
(uint32_t)(void*)::bitvm::buffer::fill, // P2 bvm {shim:buffer::fill}
|
||||
(uint32_t)(void*)::bitvm::buffer::fill_random, // P1 bvm {shim:buffer::fill_random}
|
||||
(uint32_t)(void*)::bitvm::buffer::mk, // F1 bvm {shim:buffer::mk}
|
||||
(uint32_t)(void*)::bitvm::buffer::set, // P3 bvm {shim:buffer::set}
|
||||
(uint32_t)(void*)::bitvm::collection::add, // P2 bvm {shim:collection::add}
|
||||
(uint32_t)(void*)::bitvm::collection::at, // F2 bvm {shim:collection::at}
|
||||
(uint32_t)(void*)::bitvm::collection::count, // F1 bvm {shim:collection::count}
|
||||
(uint32_t)(void*)::bitvm::collection::index_of, // F3 bvm {shim:collection::index_of}
|
||||
(uint32_t)(void*)::bitvm::collection::mk, // F1 bvm {shim:collection::mk}
|
||||
(uint32_t)(void*)::bitvm::collection::remove, // F2 bvm {shim:collection::remove}
|
||||
(uint32_t)(void*)::bitvm::collection::remove_at, // P2 bvm {shim:collection::remove_at}
|
||||
(uint32_t)(void*)::bitvm::collection::set_at, // P3 bvm {shim:collection::set_at}
|
||||
(uint32_t)(void*)::bitvm::contract::assert, // P2 bvm {shim:contract::assert}
|
||||
(uint32_t)(void*)::touch_develop::math::abs, // F1 {shim:math::abs}
|
||||
(uint32_t)(void*)::touch_develop::math::clamp, // F3 {shim:math::clamp}
|
||||
(uint32_t)(void*)::touch_develop::math::max, // F2 {shim:math::max}
|
||||
(uint32_t)(void*)::touch_develop::math::min, // F2 {shim:math::min}
|
||||
(uint32_t)(void*)::touch_develop::math::mod, // F2 {shim:math::mod}
|
||||
(uint32_t)(void*)::touch_develop::math::pow, // F2 {shim:math::pow}
|
||||
(uint32_t)(void*)::touch_develop::math::random, // F1 {shim:math::random}
|
||||
(uint32_t)(void*)::touch_develop::math::sign, // F1 {shim:math::sign}
|
||||
(uint32_t)(void*)::touch_develop::math::sqrt, // F1 {shim:math::sqrt}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::analogReadPin, // F1 {shim:micro_bit::analogReadPin}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::analogWritePin, // P2 {shim:micro_bit::analogWritePin}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::broadcastMessage, // P1 {shim:micro_bit::broadcastMessage}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::clearImage, // P1 over {shim:micro_bit::clearImage}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::clearScreen, // P0 {shim:micro_bit::clearScreen}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::compassHeading, // F0 {shim:micro_bit::compassHeading}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::createImage, // F1 over {shim:micro_bit::createImage}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::createImageFromString, // F1 over {shim:micro_bit::createImageFromString}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::createReadOnlyImage, // F1 over {shim:micro_bit::createReadOnlyImage}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::datagramGetNumber, // F1 {shim:micro_bit::datagramGetNumber}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::datagramGetRSSI, // F0 {shim:micro_bit::datagramGetRSSI}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::datagramReceiveNumber, // F0 {shim:micro_bit::datagramReceiveNumber}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::datagramSendNumber, // P1 {shim:micro_bit::datagramSendNumber}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::datagramSendNumbers, // P4 {shim:micro_bit::datagramSendNumbers}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::devices::alert, // P1 {shim:micro_bit::devices::alert}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::devices::camera, // P1 {shim:micro_bit::devices::camera}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::devices::remote_control, // P1 {shim:micro_bit::devices::remote_control}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::digitalReadPin, // F1 {shim:micro_bit::digitalReadPin}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::digitalWritePin, // P2 {shim:micro_bit::digitalWritePin}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::dispatchEvent, // P1 over {shim:micro_bit::dispatchEvent}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::displayScreenShot, // F0 over {shim:micro_bit::displayScreenShot}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::displayStopAnimation, // P0 over {shim:micro_bit::displayStopAnimation}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::enablePitch, // P1 {shim:micro_bit::enablePitch}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::fiberDone, // P1 over {shim:micro_bit::fiberDone}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::forever, // P1 over {shim:micro_bit::forever}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::forever_stub, // P1 over {shim:micro_bit::forever_stub}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::generate_event, // P2 {shim:micro_bit::generate_event}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::getAcceleration, // F1 {shim:micro_bit::getAcceleration}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::getBrightness, // F0 {shim:micro_bit::getBrightness}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::getCurrentTime, // F0 {shim:micro_bit::getCurrentTime}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::getImageHeight, // F1 over {shim:micro_bit::getImageHeight}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::getImagePixel, // F3 over {shim:micro_bit::getImagePixel}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::getImageWidth, // F1 over {shim:micro_bit::getImageWidth}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::getMagneticForce, // F1 {shim:micro_bit::getMagneticForce}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::getRotation, // F1 {shim:micro_bit::getRotation}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::i2cReadBuffer, // P2 over {shim:micro_bit::i2cReadBuffer}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::i2cReadRaw, // F4 over {shim:micro_bit::i2cReadRaw}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::i2cWriteBuffer, // P2 over {shim:micro_bit::i2cWriteBuffer}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::i2cWriteRaw, // F4 over {shim:micro_bit::i2cWriteRaw}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::i2c_read, // F1 {shim:micro_bit::i2c_read}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::i2c_write, // P2 {shim:micro_bit::i2c_write}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::i2c_write2, // P3 {shim:micro_bit::i2c_write2}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::imageClone, // F1 over {shim:micro_bit::imageClone}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::initSignalStrength, // P0 {shim:micro_bit::initSignalStrength}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP0, // F0 over {shim:micro_bit::ioP0}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP1, // F0 over {shim:micro_bit::ioP1}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP10, // F0 over {shim:micro_bit::ioP10}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP11, // F0 over {shim:micro_bit::ioP11}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP12, // F0 over {shim:micro_bit::ioP12}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP13, // F0 over {shim:micro_bit::ioP13}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP14, // F0 over {shim:micro_bit::ioP14}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP15, // F0 over {shim:micro_bit::ioP15}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP16, // F0 over {shim:micro_bit::ioP16}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP19, // F0 over {shim:micro_bit::ioP19}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP2, // F0 over {shim:micro_bit::ioP2}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP20, // F0 over {shim:micro_bit::ioP20}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP3, // F0 over {shim:micro_bit::ioP3}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP4, // F0 over {shim:micro_bit::ioP4}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP5, // F0 over {shim:micro_bit::ioP5}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP6, // F0 over {shim:micro_bit::ioP6}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP7, // F0 over {shim:micro_bit::ioP7}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP8, // F0 over {shim:micro_bit::ioP8}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::ioP9, // F0 over {shim:micro_bit::ioP9}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::isButtonPressed, // F1 {shim:micro_bit::isButtonPressed}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::isImageReadOnly, // F1 over {shim:micro_bit::isImageReadOnly}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::isPinTouched, // F1 {shim:micro_bit::isPinTouched}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::lightLevel, // F0 {shim:micro_bit::lightLevel}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onBroadcastMessageReceived, // P2 over {shim:micro_bit::onBroadcastMessageReceived}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onButtonPressed, // P2 over {shim:micro_bit::onButtonPressed}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onButtonPressedExt, // P3 over {shim:micro_bit::onButtonPressedExt}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onDatagramReceived, // P1 over {shim:micro_bit::onDatagramReceived}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onDeviceInfo, // P2 over {shim:micro_bit::onDeviceInfo}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onGamepadButton, // P2 over {shim:micro_bit::onGamepadButton}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onGesture, // P2 over {shim:micro_bit::onGesture}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onPinPressed, // P2 over {shim:micro_bit::onPinPressed}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::onSignalStrengthChanged, // P1 over {shim:micro_bit::onSignalStrengthChanged}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::on_event, // P2 over {shim:micro_bit::on_event}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::panic, // P1 over {shim:micro_bit::panic}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::pause, // P1 {shim:micro_bit::pause}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::pitch, // P2 {shim:micro_bit::pitch}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::plot, // P2 {shim:micro_bit::plot}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::plotImage, // P2 over {shim:micro_bit::plotImage}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::plotLeds, // P1 over {shim:micro_bit::plotLeds}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::point, // F2 {shim:micro_bit::point}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::radioEnable, // F0 {shim:micro_bit::radioEnable}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::registerWithDal, // P3 over {shim:micro_bit::registerWithDal}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::reset, // P0 over {shim:micro_bit::reset}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::runInBackground, // P1 over {shim:micro_bit::runInBackground}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::scrollImage, // P3 over {shim:micro_bit::scrollImage}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::scrollNumber, // P2 {shim:micro_bit::scrollNumber}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::scrollString, // P2 over {shim:micro_bit::scrollString}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::serialReadDisplayState, // P0 over {shim:micro_bit::serialReadDisplayState}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::serialReadImage, // F2 over {shim:micro_bit::serialReadImage}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::serialReadString, // F0 over {shim:micro_bit::serialReadString}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::serialSendDisplayState, // P0 over {shim:micro_bit::serialSendDisplayState}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::serialSendImage, // P1 over {shim:micro_bit::serialSendImage}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::serialSendString, // P1 over {shim:micro_bit::serialSendString}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::servoWritePin, // P2 {shim:micro_bit::servoWritePin}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setAccelerometerRange, // P1 {shim:micro_bit::setAccelerometerRange}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setAnalogPeriodUs, // P2 {shim:micro_bit::setAnalogPeriodUs}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setBrightness, // P1 {shim:micro_bit::setBrightness}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setDisplayMode, // P1 {shim:micro_bit::setDisplayMode}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setGroup, // P1 {shim:micro_bit::setGroup}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::setImagePixel, // P4 over {shim:micro_bit::setImagePixel}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setServoPulseUs, // P2 {shim:micro_bit::setServoPulseUs}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::setTransmitPower, // P1 {shim:micro_bit::setTransmitPower}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::showAnimation, // P2 over {shim:micro_bit::showAnimation}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::showDigit, // P1 {shim:micro_bit::showDigit}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::showImage, // P2 over {shim:micro_bit::showImage}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::showLeds, // P2 over {shim:micro_bit::showLeds}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::showLetter, // P1 over {shim:micro_bit::showLetter}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::signalStrength, // F0 {shim:micro_bit::signalStrength}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::signalStrengthHandler, // P1 {shim:micro_bit::signalStrengthHandler}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::stopAnimation, // P0 {shim:micro_bit::stopAnimation}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::temperature, // F0 {shim:micro_bit::temperature}
|
||||
(uint32_t)(void*)::bitvm::bitvm_micro_bit::thermometerGetTemperature, // F0 over {shim:micro_bit::thermometerGetTemperature}
|
||||
(uint32_t)(void*)::touch_develop::micro_bit::unPlot, // P2 {shim:micro_bit::unPlot}
|
||||
(uint32_t)(void*)::touch_develop::number::add, // F2 {shim:number::add}
|
||||
(uint32_t)(void*)::touch_develop::number::divide, // F2 {shim:number::divide}
|
||||
(uint32_t)(void*)::touch_develop::number::eq, // F2 {shim:number::eq}
|
||||
(uint32_t)(void*)::touch_develop::number::ge, // F2 {shim:number::ge}
|
||||
(uint32_t)(void*)::touch_develop::number::gt, // F2 {shim:number::gt}
|
||||
(uint32_t)(void*)::touch_develop::number::le, // F2 {shim:number::le}
|
||||
(uint32_t)(void*)::touch_develop::number::lt, // F2 {shim:number::lt}
|
||||
(uint32_t)(void*)::touch_develop::number::multiply, // F2 {shim:number::multiply}
|
||||
(uint32_t)(void*)::touch_develop::number::neq, // F2 {shim:number::neq}
|
||||
(uint32_t)(void*)::bitvm::bitvm_number::post_to_wall, // P1 over {shim:number::post_to_wall}
|
||||
(uint32_t)(void*)::touch_develop::number::subtract, // F2 {shim:number::subtract}
|
||||
(uint32_t)(void*)::bitvm::bitvm_number::to_character, // F1 over {shim:number::to_character}
|
||||
(uint32_t)(void*)::bitvm::bitvm_number::to_string, // F1 over {shim:number::to_string}
|
||||
(uint32_t)(void*)::bitvm::record::mk, // F2 bvm {shim:record::mk}
|
||||
(uint32_t)(void*)::touch_develop::string::_, // F2 {shim:string::_}
|
||||
(uint32_t)(void*)::bitvm::string::at, // F2 bvm {shim:string::at}
|
||||
(uint32_t)(void*)::bitvm::string::code_at, // F2 bvm {shim:string::code_at}
|
||||
(uint32_t)(void*)::bitvm::string::concat, // F2 bvm {shim:string::concat}
|
||||
(uint32_t)(void*)::bitvm::string::concat_op, // F2 bvm {shim:string::concat_op}
|
||||
(uint32_t)(void*)::bitvm::string::count, // F1 bvm {shim:string::count}
|
||||
(uint32_t)(void*)::bitvm::string::equals, // F2 bvm {shim:string::equals}
|
||||
(uint32_t)(void*)::bitvm::string::mkEmpty, // F0 bvm {shim:string::mkEmpty}
|
||||
(uint32_t)(void*)::bitvm::string::post_to_wall, // P1 bvm {shim:string::post_to_wall}
|
||||
(uint32_t)(void*)::bitvm::string::substring, // F3 bvm {shim:string::substring}
|
||||
(uint32_t)(void*)::bitvm::string::to_character_code, // F1 bvm {shim:string::to_character_code}
|
||||
(uint32_t)(void*)::bitvm::string::to_number, // F1 bvm {shim:string::to_number}
|
||||
(uint32_t)(void*)::touch_develop::dispatchEvent, // P1 {shim:touch_develop::dispatchEvent}
|
||||
(uint32_t)(void*)::touch_develop::internal_main, // P0 {shim:touch_develop::internal_main}
|
||||
(uint32_t)(void*)::touch_develop::touch_develop::mk_string, // F1 {shim:touch_develop::mk_string}
|
||||
(uint32_t)(void*)::wait_us, // P1 {shim:wait_us}
|
|
@ -1,26 +0,0 @@
|
|||
#include "MicroBitTouchDevelop.h"
|
||||
|
||||
/* This module provides some useful i2c wrappers for common patterns, such as
|
||||
* writing into a register and reading a one-byte or two-byte value afterwards.
|
||||
* */
|
||||
|
||||
#ifndef __MICROBIT_I2CCOMMON_H
|
||||
#define __MICROBIT_I2CCOMMON_H
|
||||
|
||||
namespace touch_develop {
|
||||
namespace i2c {
|
||||
class I2CSimple {
|
||||
public:
|
||||
I2CSimple(char addr, char mask = 0);
|
||||
uint8_t read8(char reg);
|
||||
uint16_t read16(char reg);
|
||||
int16_t readS16(char reg);
|
||||
void write8(char reg, char val);
|
||||
private:
|
||||
char addr;
|
||||
char mask;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* MicroBitCustomConfig.h
|
||||
*
|
||||
* This file is automatically included by the microbit DAL compilation
|
||||
* process. Use this to define any custom configuration options needed
|
||||
* for your build of the micro:bit runtime.
|
||||
*
|
||||
* See microbit-dal/inc/MicroBitConfig.h for a complete list of options.
|
||||
* Any options you define here will take precedence over those defined there.
|
||||
*/
|
||||
|
||||
#ifndef MICROBIT_CUSTOM_CONFIG_H
|
||||
#define MICROBIT_CUSTOM_CONFIG_H
|
||||
|
||||
// Define your configuration options here.
|
||||
// #define MICROBIT_DBG 1
|
||||
|
||||
#undef MESSAGE_BUS_LISTENER_DEFAULT_FLAGS
|
||||
#define MESSAGE_BUS_LISTENER_DEFAULT_FLAGS MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY
|
||||
|
||||
#include "ext/config.h"
|
||||
|
||||
#endif
|
|
@ -1,482 +0,0 @@
|
|||
#include "MicroBitCustomConfig.h"
|
||||
|
||||
#if __cplusplus <= 199711L
|
||||
#error The glue layer requires C++11 support. Please use GCC 4.9.3 or greater.
|
||||
#endif
|
||||
|
||||
#ifndef __MICROBIT_TOUCHDEVELOP_H
|
||||
#define __MICROBIT_TOUCHDEVELOP_H
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "MicroBit.h"
|
||||
#include "MicroBitImage.h"
|
||||
#include "ManagedString.h"
|
||||
#include "ManagedType.h"
|
||||
|
||||
#define TD_NOOP(...)
|
||||
#define TD_ID(x) x
|
||||
|
||||
namespace touch_develop {
|
||||
|
||||
using std::map;
|
||||
using std::unique_ptr;
|
||||
using std::pair;
|
||||
using std::function;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Base definitions that may be referred to by the C++ compiler.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
enum TdError {
|
||||
TD_UNINITIALIZED_OBJECT_TYPE = 40,
|
||||
TD_OUT_OF_BOUNDS,
|
||||
TD_BAD_USAGE,
|
||||
TD_CONTRACT_ERROR,
|
||||
TD_PERIPHERAL_ERROR,
|
||||
};
|
||||
|
||||
namespace touch_develop {
|
||||
ManagedString mk_string(char* c);
|
||||
|
||||
template <typename T>
|
||||
inline bool is_null(T* p) {
|
||||
return p == NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// An adapter for the API expected by the run-time.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// We maintain a mapping from source/event to the current event handler. In
|
||||
// order to implement the TouchDevelop semantics of "at most one event handler
|
||||
// per source/event pair", every event is dispatched through [dispatchEvent],
|
||||
// which then does a table lookup to figure out the current handler.
|
||||
|
||||
extern map<pair<int, int>, function<void (MicroBitEvent)>> handlersMap;
|
||||
void dispatchEvent(MicroBitEvent e);
|
||||
void registerHandler(pair<int, int>, function<void()>);
|
||||
void registerHandler(pair<int, int>, function<void(int)>);
|
||||
|
||||
template <typename T> // T: function<void()> or T: function<void(int)>
|
||||
inline void registerWithDal(int id, int event, T f) {
|
||||
if (!handlersMap[{ id, event }])
|
||||
uBit.MessageBus.listen(id, event, dispatchEvent);
|
||||
registerHandler({ id, event }, f);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implementation of the base TouchDevelop types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef int Number;
|
||||
typedef bool Boolean;
|
||||
typedef ManagedString String;
|
||||
template <typename T> using Collection_of = ManagedType<vector<T>>;
|
||||
template <typename T> using Collection = ManagedType<vector<T>>;
|
||||
|
||||
// A short override of [ManagedType] to make the generated code more compact.
|
||||
template <typename T>
|
||||
class Ref: public ManagedType<T> {
|
||||
public:
|
||||
Ref();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Ref<T>::Ref() {
|
||||
this->object = new T();
|
||||
*(this->ref) = 1;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implementation of the base TouchDevelop libraries and operations
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace contract {
|
||||
void assert(bool x, ManagedString msg);
|
||||
}
|
||||
|
||||
|
||||
namespace string {
|
||||
ManagedString concat(ManagedString s1, ManagedString s2);
|
||||
|
||||
ManagedString _(ManagedString s1, ManagedString s2);
|
||||
|
||||
ManagedString substring(ManagedString s, int i, int j);
|
||||
|
||||
bool equals(ManagedString s1, ManagedString s2);
|
||||
|
||||
int count(ManagedString s);
|
||||
|
||||
ManagedString at(ManagedString s, int i);
|
||||
|
||||
int to_character_code(ManagedString s);
|
||||
|
||||
int code_at(ManagedString s, int i);
|
||||
|
||||
int to_number(ManagedString s);
|
||||
|
||||
void post_to_wall(ManagedString s);
|
||||
}
|
||||
|
||||
namespace math {
|
||||
int max(int x, int y);
|
||||
int min(int x, int y);
|
||||
int random(int max);
|
||||
// Unspecified behavior for int_min
|
||||
int abs(int x);
|
||||
int mod (int x, int y);
|
||||
|
||||
int pow(int x, int n);
|
||||
|
||||
int clamp(int l, int h, int x);
|
||||
|
||||
int sqrt(int x);
|
||||
|
||||
int sign(int x);
|
||||
}
|
||||
|
||||
namespace number {
|
||||
bool lt(int x, int y);
|
||||
bool le(int x, int y);
|
||||
bool neq(int x, int y);
|
||||
bool eq(int x, int y);
|
||||
bool gt(int x, int y);
|
||||
bool ge(int x, int y);
|
||||
int add(int x, int y);
|
||||
int subtract(int x, int y);
|
||||
int divide(int x, int y);
|
||||
int multiply(int x, int y);
|
||||
ManagedString to_string(int x);
|
||||
ManagedString to_character(int x);
|
||||
void post_to_wall(int s);
|
||||
}
|
||||
|
||||
namespace bits {
|
||||
int or_uint32(int x, int y);
|
||||
int and_uint32(int x, int y);
|
||||
int xor_uint32(int x, int y);
|
||||
int shift_left_uint32(int x, int y);
|
||||
int shift_right_uint32(int x, int y);
|
||||
int rotate_right_uint32(int x, int y);
|
||||
int rotate_left_uint32(int x, int y);
|
||||
}
|
||||
|
||||
namespace boolean {
|
||||
bool or_(bool x, bool y);
|
||||
bool and_(bool x, bool y);
|
||||
bool not_(bool x);
|
||||
bool equals(bool x, bool y);
|
||||
ManagedString to_string(bool x);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Some extra TouchDevelop libraries (Collection, Ref, ...)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Parameterized types only work if we have the C++11-style "using" typedef.
|
||||
namespace create {
|
||||
template<typename T>
|
||||
inline Collection_of<T> collection_of() {
|
||||
return ManagedType<vector<T>>(new vector<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Ref<T> ref_of() {
|
||||
return Ref<T>();
|
||||
}
|
||||
}
|
||||
|
||||
namespace collection {
|
||||
template<typename T>
|
||||
inline Number count(Collection_of<T> c) {
|
||||
if (c.get() != NULL)
|
||||
return c->size();
|
||||
else
|
||||
uBit.panic(TD_UNINITIALIZED_OBJECT_TYPE);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void add(Collection_of<T> c, T x) {
|
||||
if (c.get() != NULL)
|
||||
c->push_back(x);
|
||||
else
|
||||
uBit.panic(TD_UNINITIALIZED_OBJECT_TYPE);
|
||||
}
|
||||
|
||||
// First check that [c] is valid (panic if not), then proceed to check that
|
||||
// [x] is within bounds.
|
||||
template<typename T>
|
||||
inline bool in_range(Collection_of<T> c, int x) {
|
||||
if (c.get() != NULL)
|
||||
return (0 <= x && x < c->size());
|
||||
else
|
||||
uBit.panic(TD_UNINITIALIZED_OBJECT_TYPE);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T at(Collection_of<T> c, int x) {
|
||||
if (in_range(c, x))
|
||||
return c->at(x);
|
||||
else
|
||||
uBit.panic(TD_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void remove_at(Collection_of<T> c, int x) {
|
||||
if (!in_range(c, x))
|
||||
return;
|
||||
|
||||
c->erase(c->begin()+x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void set_at(Collection_of<T> c, int x, T y) {
|
||||
if (!in_range(c, x))
|
||||
return;
|
||||
|
||||
c->at(x) = y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Number index_of(Collection_of<T> c, T x, int start) {
|
||||
if (!in_range(c, start))
|
||||
return -1;
|
||||
|
||||
int index = -1;
|
||||
for (int i = start; i < c->size(); ++i)
|
||||
if (c->at(i) == x)
|
||||
index = i;
|
||||
return index;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void remove(Collection_of<T> c, T x) {
|
||||
remove_at(c, index_of(c, x, 0));
|
||||
}
|
||||
}
|
||||
|
||||
namespace ref {
|
||||
template<typename T>
|
||||
inline T _get(Ref<T> x) {
|
||||
return *(x.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void _set(Ref<T> x, T y) {
|
||||
*(x.get()) = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implementation of the BBC micro:bit features
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace micro_bit {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Sensors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
int compassHeading();
|
||||
|
||||
int lightLevel();
|
||||
|
||||
int temperature();
|
||||
|
||||
// in micro Tesla
|
||||
// x = 0, y = 1, z = 2, strength = 3
|
||||
int getMagneticForce(int dimension);
|
||||
|
||||
// x = 0, y = 1, z = 2, strength = 3
|
||||
int getAcceleration(int dimension);
|
||||
|
||||
void setAccelerometerRange(int range);
|
||||
|
||||
// pitch = 0, roll = 1
|
||||
int getRotation(int dimension);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Radio
|
||||
// -------------------------------------------------------------------------
|
||||
extern uint8_t radioDefaultGroup;
|
||||
int radioEnable();
|
||||
|
||||
void setGroup(int id);
|
||||
|
||||
void setTransmitPower(int power);
|
||||
|
||||
void broadcastMessage(int message);
|
||||
|
||||
void onBroadcastMessageReceived(int message, function<void()> f);
|
||||
// -------------------------------------------------------------------------
|
||||
// Buttons
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
bool isButtonPressed(int button);
|
||||
void onButtonPressedExt(int button, int event, function<void()> f);
|
||||
void onButtonPressed(int button, function<void()> f);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Pins
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
int analogReadPin(MicroBitPin& p);
|
||||
|
||||
void analogWritePin(MicroBitPin& p, int value);
|
||||
|
||||
void setAnalogPeriodUs(MicroBitPin& p, int micros);
|
||||
|
||||
void servoWritePin(MicroBitPin& p, int value);
|
||||
|
||||
void setServoPulseUs(MicroBitPin& p, int micros);
|
||||
|
||||
int digitalReadPin(MicroBitPin& p);
|
||||
|
||||
void digitalWritePin(MicroBitPin& p, int value);
|
||||
|
||||
bool isPinTouched(MicroBitPin& pin);
|
||||
|
||||
void onPinPressed(int pin, function<void()> f);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// System
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void runInBackground(function<void()> f);
|
||||
|
||||
void pause(int ms);
|
||||
|
||||
void forever(function<void()> f);
|
||||
|
||||
int getCurrentTime();
|
||||
|
||||
int i2c_read(int addr);
|
||||
|
||||
void i2c_write(int addr, char c);
|
||||
|
||||
void i2c_write2(int addr, int c1, int c2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Screen (reading/modifying the global, mutable state of the display)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
int getBrightness();
|
||||
|
||||
void setBrightness(int percentage);
|
||||
|
||||
void clearScreen();
|
||||
|
||||
void setDisplayMode(int mode);
|
||||
|
||||
void plot(int x, int y);
|
||||
|
||||
void unPlot(int x, int y);
|
||||
|
||||
bool point(int x, int y);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Images (helpers that create/modify a MicroBitImage)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Argument rewritten by the C++ emitter to be what we need
|
||||
MicroBitImage createImage(int w, int h, const uint8_t* bitmap);
|
||||
|
||||
MicroBitImage createImageFromString(ManagedString s);
|
||||
|
||||
void clearImage(MicroBitImage i);
|
||||
|
||||
int getImagePixel(MicroBitImage i, int x, int y);
|
||||
|
||||
void setImagePixel(MicroBitImage i, int x, int y, int value);
|
||||
|
||||
int getImageWidth(MicroBitImage i);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Various "show"-style functions to display and scroll things on the screen
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void showLetter(ManagedString s);
|
||||
|
||||
void showDigit(int n);
|
||||
|
||||
void scrollNumber(int n, int delay);
|
||||
|
||||
void scrollString(ManagedString s, int delay);
|
||||
|
||||
void plotImage(MicroBitImage i, int offset);
|
||||
|
||||
void plotLeds(int w, int h, const uint8_t* bitmap);
|
||||
|
||||
void showImage(MicroBitImage i, int offset);
|
||||
|
||||
// These have their arguments rewritten by the C++ compiler.
|
||||
void showLeds(int w, int h, const uint8_t* bitmap, int delay);
|
||||
|
||||
void scrollImage(MicroBitImage i, int offset, int delay);
|
||||
|
||||
void showAnimation(int w, int h, const uint8_t* bitmap, int ms);
|
||||
|
||||
void stopAnimation();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// BLE Events
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void generate_event(int id, int event);
|
||||
|
||||
void on_event(int id, function<void*(int)> f);
|
||||
|
||||
void onDeviceInfo(int event, function<void()> f);
|
||||
|
||||
extern int _signalStrength;
|
||||
int signalStrength();
|
||||
void initSignalStrength();
|
||||
void signalStrengthHandler(MicroBitEvent ev);
|
||||
void onSignalStrengthChanged(function<void()> f);
|
||||
void onGamepadButton(int id, function<void()> f);
|
||||
|
||||
void datagramSendNumber(int value);
|
||||
void datagramSendNumbers(int value0, int value1, int value2, int value3);
|
||||
int datagramReceiveNumber();
|
||||
int datagramGetNumber(int index);
|
||||
int datagramGetRSSI();
|
||||
void onDatagramReceived(function<void()> f);
|
||||
|
||||
void onGesture(int gesture, function<void()> f);
|
||||
|
||||
namespace devices {
|
||||
void remote_control(int event);
|
||||
void camera(int event);
|
||||
void alert(int event);
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Music
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void enablePitch(MicroBitPin& p);
|
||||
|
||||
void pitch(int freq, int ms);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Called at start-up by the generated code (currently not enabled).
|
||||
// -------------------------------------------------------------------------
|
||||
void internal_main();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// vim: set ts=2 sw=2 sts=2:
|
|
@ -1,20 +1,18 @@
|
|||
#ifndef __BITVM_H
|
||||
#define __BITVM_H
|
||||
#ifndef __KINDSCRIPT_H
|
||||
#define __KINDSCRIPT_H
|
||||
|
||||
// #define DEBUG_MEMLEAKS 1
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#include "MicroBitCustomConfig.h"
|
||||
|
||||
#include "MicroBit.h"
|
||||
#include "MicroBitImage.h"
|
||||
#include "ManagedString.h"
|
||||
#include "ManagedType.h"
|
||||
|
||||
#define printf(...) uBit.serial.printf(__VA_ARGS__)
|
||||
// #define printf(...)
|
||||
|
||||
// for marking glue functions
|
||||
#define GLUE /*glue*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
@ -24,15 +22,10 @@
|
|||
#include <set>
|
||||
#endif
|
||||
|
||||
namespace bitvm {
|
||||
namespace ks {
|
||||
typedef uint32_t Action;
|
||||
typedef uint32_t ImageLiteral;
|
||||
|
||||
namespace action {
|
||||
Action mk(int reflen, int totallen, int startptr);
|
||||
void run1(Action a, int arg);
|
||||
void run(Action a);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
ERR_INVALID_BINARY_HEADER = 5,
|
||||
|
@ -41,30 +34,57 @@ namespace bitvm {
|
|||
ERR_SIZE = 9,
|
||||
} ERROR;
|
||||
|
||||
extern const uint32_t functionsAndBytecode[];
|
||||
extern uint32_t *globals;
|
||||
extern int numGlobals;
|
||||
extern uint16_t *bytecode;
|
||||
class RefRecord;
|
||||
|
||||
|
||||
inline void die() { uBit.panic(42); }
|
||||
|
||||
// Utility functions
|
||||
void registerWithDal(int id, int event, Action a);
|
||||
void runInBackground(Action a);
|
||||
void runAction0(Action a);
|
||||
void runAction1(Action a, int arg);
|
||||
Action mkAction(int reflen, int totallen, int startptr);
|
||||
void error(ERROR code, int subcode = 0);
|
||||
void exec_binary(uint16_t *pc);
|
||||
void start();
|
||||
void debugMemLeaks();
|
||||
// allocate [sz] words and clear them
|
||||
uint32_t *allocate(uint16_t sz);
|
||||
int templateHash();
|
||||
int programHash();
|
||||
RefRecord* mkRecord(int reflen, int totallen);
|
||||
|
||||
// The standard calling convention is:
|
||||
// - when a pointer is loaded from a local/global/field etc, and incr()ed
|
||||
// (in other words, its presence on stack counts as a reference)
|
||||
// - after a function call, all pointers are popped off the stack and decr()ed
|
||||
// This does not apply to the RefRecord and st/ld(ref) methods - they unref()
|
||||
// the RefRecord* this.
|
||||
int incr(uint32_t e);
|
||||
void decr(uint32_t e);
|
||||
|
||||
inline void *ptrOfLiteral(int offset)
|
||||
{
|
||||
return &bytecode[offset];
|
||||
}
|
||||
|
||||
inline ImageData* imageBytes(int offset)
|
||||
{
|
||||
return (ImageData*)(void*)&bytecode[offset];
|
||||
}
|
||||
|
||||
|
||||
inline void check(int cond, ERROR code, int subcode = 0)
|
||||
{
|
||||
if (!cond) error(code, subcode);
|
||||
}
|
||||
|
||||
void exec_binary(uint16_t *pc);
|
||||
void start();
|
||||
|
||||
extern const uint32_t functionsAndBytecode[];
|
||||
extern uint16_t *bytecode;
|
||||
|
||||
|
||||
#ifdef DEBUG_MEMLEAKS
|
||||
class RefObject;
|
||||
extern std::set<RefObject*> allptrs;
|
||||
void debugMemLeaks();
|
||||
#endif
|
||||
|
||||
// A base abstract class for ref-counted objects.
|
||||
|
@ -81,8 +101,7 @@ namespace bitvm {
|
|||
#endif
|
||||
}
|
||||
|
||||
// Call to disable pointer tracking on the current instance. Currently used
|
||||
// by string literals.
|
||||
// Call to disable pointer tracking on the current instance.
|
||||
void canLeak()
|
||||
{
|
||||
#ifdef DEBUG_MEMLEAKS
|
||||
|
@ -128,41 +147,11 @@ namespace bitvm {
|
|||
};
|
||||
|
||||
// Checks if object has a VTable, or if its RefCounted* from the runtime.
|
||||
// XXX 'inline' needs to be on separate line for embedding script
|
||||
inline
|
||||
bool hasVTable(uint32_t e)
|
||||
inline bool hasVTable(uint32_t e)
|
||||
{
|
||||
return (*((uint32_t*)e) & 1) == 0;
|
||||
}
|
||||
|
||||
// The standard calling convention is:
|
||||
// - when a pointer is loaded from a local/global/field etc, and incr()ed
|
||||
// (in other words, its presence on stack counts as a reference)
|
||||
// - after a function call, all pointers are popped off the stack and decr()ed
|
||||
// This does not apply to the RefRecord and st/ld(ref) methods - they unref()
|
||||
// the RefRecord* this.
|
||||
inline
|
||||
void incr(uint32_t e)
|
||||
{
|
||||
if (e) {
|
||||
if (hasVTable(e))
|
||||
((RefObject*)e)->ref();
|
||||
else
|
||||
((RefCounted*)e)->incr();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void decr(uint32_t e)
|
||||
{
|
||||
if (e) {
|
||||
if (hasVTable(e))
|
||||
((RefObject*)e)->unref();
|
||||
else
|
||||
((RefCounted*)e)->decr();
|
||||
}
|
||||
}
|
||||
|
||||
// Ref-counted wrapper around any C++ object.
|
||||
template <class T>
|
||||
class RefStruct
|
||||
|
@ -214,6 +203,19 @@ namespace bitvm {
|
|||
{
|
||||
printf("RefCollection %p r=%d flags=%d size=%d [%p, ...]\n", this, refcnt, flags, data.size(), data.size() > 0 ? data[0] : 0);
|
||||
}
|
||||
|
||||
inline bool in_range(int x) {
|
||||
return (0 <= x && x < (int)data.size());
|
||||
}
|
||||
|
||||
inline int length() { return data.size(); }
|
||||
|
||||
void push(uint32_t x);
|
||||
uint32_t getAt(int x);
|
||||
void removeAt(int x);
|
||||
void setAt(int x, uint32_t y);
|
||||
int indexOf(uint32_t x, int start);
|
||||
int removeElement(uint32_t x);
|
||||
};
|
||||
|
||||
// A ref-counted byte buffer
|
||||
|
@ -232,6 +234,10 @@ namespace bitvm {
|
|||
{
|
||||
printf("RefBuffer %p r=%d size=%d [%p, ...]\n", this, refcnt, data.size(), data.size() > 0 ? data[0] : 0);
|
||||
}
|
||||
|
||||
char *cptr() { return (char*)&data[0]; }
|
||||
int size() { return data.size(); }
|
||||
|
||||
};
|
||||
|
||||
// A ref-counted, user-defined Touch Develop object.
|
||||
|
@ -247,48 +253,14 @@ namespace bitvm {
|
|||
// The object is allocated, so that there is space at the end for the fields.
|
||||
uint32_t fields[];
|
||||
|
||||
virtual ~RefRecord()
|
||||
{
|
||||
//printf("DELREC: %p\n", this);
|
||||
for (int i = 0; i < this->reflen; ++i) {
|
||||
decr(fields[i]);
|
||||
fields[i] = 0;
|
||||
}
|
||||
}
|
||||
virtual ~RefRecord();
|
||||
virtual void print();
|
||||
|
||||
virtual void print()
|
||||
{
|
||||
printf("RefRecord %p r=%d size=%d (%d refs)\n", this, refcnt, len, reflen);
|
||||
}
|
||||
uint32_t ld(int idx);
|
||||
uint32_t ldref(int idx);
|
||||
void st(int idx, uint32_t v);
|
||||
void stref(int idx, uint32_t v);
|
||||
|
||||
inline uint32_t ld(int idx)
|
||||
{
|
||||
check(reflen <= idx && idx < len, ERR_OUT_OF_BOUNDS, 1);
|
||||
return fields[idx];
|
||||
}
|
||||
|
||||
inline uint32_t ldref(int idx)
|
||||
{
|
||||
//printf("LD %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
|
||||
check(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 2);
|
||||
uint32_t tmp = fields[idx];
|
||||
incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline void st(int idx, uint32_t v)
|
||||
{
|
||||
check(reflen <= idx && idx < len, ERR_OUT_OF_BOUNDS, 3);
|
||||
fields[idx] = v;
|
||||
}
|
||||
|
||||
inline void stref(int idx, uint32_t v)
|
||||
{
|
||||
//printf("ST %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
|
||||
check(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 4);
|
||||
decr(fields[idx]);
|
||||
fields[idx] = v;
|
||||
}
|
||||
};
|
||||
|
||||
class RefAction;
|
||||
|
@ -327,7 +299,7 @@ namespace bitvm {
|
|||
fields[idx] = v;
|
||||
}
|
||||
|
||||
inline uint32_t run(int arg)
|
||||
inline uint32_t runCore(int arg) // use runAction*()
|
||||
{
|
||||
this->ref();
|
||||
uint32_t r = this->func(this, &this->fields[0], arg);
|
||||
|
@ -369,18 +341,21 @@ namespace bitvm {
|
|||
decr(v);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using namespace bitvm;
|
||||
// The ARM Thumb generator in the JavaScript code is parsing
|
||||
// the hex file and looks for the magic numbers as present here.
|
||||
//
|
||||
// Then it fetches function pointer addresses from there.
|
||||
|
||||
#define KS_SHIMS_BEGIN \
|
||||
namespace ks { \
|
||||
const uint32_t functionsAndBytecode[] __attribute__((aligned(0x20))) = { \
|
||||
0x08010801, 0x42424242, 0x08010801, 0x8de9d83e, \
|
||||
|
||||
#define getstr(off) ((const char*)&bytecode[off])
|
||||
#define getbytes(off) ((ImageData*)(void*)&bytecode[off])
|
||||
#define KS_SHIMS_END }; }
|
||||
|
||||
#endif
|
||||
|
||||
/* mbed functions to import. The pointer-table generation script will pick these up. */
|
||||
#if POINTER_GENERATOR_DOESNT_REALLY_DO_IFDEFS
|
||||
void wait_us(int us);
|
||||
#endif
|
||||
|
||||
// vim: ts=2 sw=2 expandtab
|
3
run.sh
3
run.sh
|
@ -5,7 +5,4 @@ set -e
|
|||
mkdir -p build
|
||||
yotta target bbc-microbit-classic-gcc
|
||||
yotta update
|
||||
node scripts/functionTable.js inc/BitVM.h inc/MicroBitTouchDevelop.h source/bitvm.cpp yotta_modules/microbit-dal/inc/*.h
|
||||
mkdir -p ext
|
||||
touch ext/config.h ext/pointers.inc ext/refs.inc
|
||||
yotta build
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
console.log("Generate JSON metadata and .cpp file with function table.")
|
||||
console.log("USAGE: node generateEmbedInfo.js file.cpp/h...")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var funs = {}
|
||||
|
||||
var prefixes = ["bitvm::bitvm_", "bitvm::", "touch_develop::", ""]
|
||||
var fullfuns = {}
|
||||
var basenames = {}
|
||||
var enums = {}
|
||||
|
||||
process.argv.slice(2).forEach(function (fn) {
|
||||
var type = null;
|
||||
var numArgs = 0;
|
||||
var idx = 0;
|
||||
|
||||
var nsStack = [];
|
||||
var lineNo = 0;
|
||||
var justPushed = true;
|
||||
nsStack.push({ ns: "", endMark: "end of file", lineNo: 0, fnIndent: "" })
|
||||
|
||||
var isInlude = /yotta_modules/.test(fn)
|
||||
|
||||
console.log("reading " + fn);
|
||||
fs.readFileSync(fn, "utf8").split(/\n/).forEach(function(ln) {
|
||||
lineNo++;
|
||||
|
||||
ln = ln.replace(/\s*$/, "")
|
||||
|
||||
if (ln == "") return;
|
||||
|
||||
if (isInlude) {
|
||||
ln = ln.replace(/\/\/.*/, "")
|
||||
m = /^\s*#define\s+(\w+)\s+(\d+)\s*$/.exec(ln)
|
||||
if (m) {
|
||||
enums[m[1]] = parseInt(m[2])
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var top = nsStack[nsStack.length - 1]
|
||||
|
||||
if (justPushed) {
|
||||
m = /^(\s*)/.exec(ln)
|
||||
top.fnIndent = m[1]
|
||||
justPushed = false;
|
||||
}
|
||||
|
||||
var m = /^(\s*)(class|namespace) (\w+)/.exec(ln)
|
||||
if (!/;$/.test(ln) && m) {
|
||||
var isClass = m[2] == "class"
|
||||
nsStack.push({ ns: m[3], endMark: m[1] + "}" + (isClass ? ";" : ""), lineNo: lineNo, isClass: isClass })
|
||||
justPushed = true;
|
||||
} else {
|
||||
if (top.endMark == ln) {
|
||||
nsStack.pop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m = /^(\s*)(\w+)([\*\&]*\s+[\*\&]*)(\w+)\s*\(([^\(\)]*)\)\s*(;\s*$|\{|$)/.exec(ln)
|
||||
if (top && m && !/^(else|return)$/.test(m[2])) {
|
||||
if (top.isClass) {
|
||||
return; // no class methods yet
|
||||
}
|
||||
if (top.fnIndent != m[1]) {
|
||||
console.log("skip by indent:", ln)
|
||||
return;
|
||||
}
|
||||
var ns = nsStack.slice(1).map(s => s.ns).filter(s => !!s).join("::")
|
||||
var name = ns + "::" + m[4]
|
||||
if (ns == "") name = m[4]
|
||||
var tp = "F"
|
||||
if (m[2] == "void" && m[3].trim() == "")
|
||||
tp = "P"
|
||||
var args = 0
|
||||
if (m[5].trim() == "")
|
||||
args = 0
|
||||
else
|
||||
args = m[5].replace(/[^,]/g, "").length + 1
|
||||
|
||||
console.log(fn + ": found " + name);
|
||||
var inf = fullfuns[name] = {
|
||||
proto: "",
|
||||
name: name,
|
||||
type: tp,
|
||||
args: args,
|
||||
full: name,
|
||||
}
|
||||
|
||||
prefixes.forEach(p => {
|
||||
if (name.slice(0, p.length) == p &&
|
||||
/::/.test(name.slice(p.length)))
|
||||
name = name.slice(p.length)
|
||||
})
|
||||
basenames[name] = 1;
|
||||
var fmt = (s,n) => s.length >= n ? s + " " : (s + " ").slice(0, n)
|
||||
var rettp = (m[2] + m[3]).replace(/\s+/, "")
|
||||
inf.proto = fmt(rettp, 15) + fmt(name, 30) + fmt("(" + m[5] + ");", 40)
|
||||
}
|
||||
})
|
||||
|
||||
if (nsStack.length != 1) {
|
||||
console.log("non-empty namespace stack", nsStack)
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
|
||||
var ptrs = ""
|
||||
var protos = ""
|
||||
var functions = []
|
||||
|
||||
var funnames = Object.keys(basenames)
|
||||
funnames.sort()
|
||||
funnames.forEach(bn => {
|
||||
for (let p of prefixes) {
|
||||
let fn = p + bn
|
||||
let inf = fullfuns[fn]
|
||||
if (inf) {
|
||||
//basenames[bn] = inf
|
||||
inf.name = bn
|
||||
if (inf.full == "touch_develop::" + bn)
|
||||
delete inf.full;
|
||||
let tp = inf.type + inf.args
|
||||
if (inf.full == "bitvm::" + bn)
|
||||
tp += " bvm"
|
||||
if (inf.full == "bitvm::bitvm_" + bn)
|
||||
tp += " over"
|
||||
ptrs += `(uint32_t)(void*)::${fn}, // ${tp} {shim:${bn}}\n`;
|
||||
functions.push(inf)
|
||||
protos += inf.proto + "// " + tp + "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var metainfo = {
|
||||
functions: functions,
|
||||
enums: enums
|
||||
}
|
||||
|
||||
function write(fn, cont)
|
||||
{
|
||||
if (fs.existsSync(fn)) {
|
||||
var curr = fs.readFileSync(fn, "utf8")
|
||||
if (curr == cont)
|
||||
return;
|
||||
}
|
||||
fs.writeFileSync(fn, cont)
|
||||
}
|
||||
|
||||
write("generated/pointers.inc", ptrs)
|
||||
write("build/protos.h", protos)
|
||||
write("generated/metainfo.json", JSON.stringify(metainfo, null, 2))
|
||||
|
||||
|
||||
// vim: ts=4 sw=4
|
|
@ -1,37 +0,0 @@
|
|||
#include "I2CCommon.h"
|
||||
|
||||
namespace touch_develop {
|
||||
namespace i2c {
|
||||
I2CSimple::I2CSimple(char addr, char mask): addr(addr), mask(mask) {}
|
||||
|
||||
uint8_t I2CSimple::read8(char reg){
|
||||
reg |= mask;
|
||||
char cmd2[] = { reg };
|
||||
uBit.i2c.write(addr << 1, cmd2, 1);
|
||||
char buf[1];
|
||||
uBit.i2c.read(addr << 1, buf, 1);
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
uint16_t I2CSimple::read16(char reg){
|
||||
reg |= mask;
|
||||
char cmd2[] = { reg };
|
||||
uBit.i2c.write(addr << 1, cmd2, 1);
|
||||
char buf[2];
|
||||
uBit.i2c.read(addr << 1, buf, 2);
|
||||
|
||||
return (((uint16_t) buf[0]) << 8) + ((uint8_t) buf[1]);
|
||||
}
|
||||
|
||||
int16_t I2CSimple::readS16(char reg){
|
||||
int16_t i = read16(reg);
|
||||
return (int16_t)i;
|
||||
}
|
||||
|
||||
void I2CSimple::write8(char reg, char value) {
|
||||
reg |= mask;
|
||||
char c[] = { reg, value };
|
||||
uBit.i2c.write(addr << 1, c, 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,754 +0,0 @@
|
|||
#include "MicroBitTouchDevelop.h"
|
||||
|
||||
namespace touch_develop {
|
||||
|
||||
using std::map;
|
||||
using std::unique_ptr;
|
||||
using std::pair;
|
||||
using std::function;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Base definitions that may be referred to by the C++ compiler.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace touch_develop {
|
||||
ManagedString mk_string(char* c) {
|
||||
return ManagedString(c);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// An adapter for the API expected by the run-time.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
map<pair<int, int>, function<void (MicroBitEvent)>> handlersMap;
|
||||
|
||||
// We have the invariant that if [dispatchEvent] is registered against the DAL
|
||||
// for a given event, then [handlersMap] contains a valid entry for that
|
||||
// event.
|
||||
void dispatchEvent(MicroBitEvent e) {
|
||||
handlersMap[{ e.source, e.value }](e);
|
||||
}
|
||||
|
||||
void registerHandler(pair<int, int> k, function<void(int)> f) {
|
||||
handlersMap[k] = [f] (MicroBitEvent e) {
|
||||
f(e.value);
|
||||
};
|
||||
}
|
||||
|
||||
void registerHandler(pair<int, int> k, function<void()> f) {
|
||||
handlersMap[k] = [f] (MicroBitEvent) {
|
||||
f();
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implementation of the base TouchDevelop libraries and operations
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace contract {
|
||||
void assert(bool x, ManagedString msg) {
|
||||
if (!x) {
|
||||
uBit.display.scroll(msg);
|
||||
uBit.panic(TD_CONTRACT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace string {
|
||||
bool in_range(ManagedString s, int i) {
|
||||
return i >= 0 && i < s.length();
|
||||
}
|
||||
|
||||
ManagedString concat(ManagedString s1, ManagedString s2) {
|
||||
return s1 + s2;
|
||||
}
|
||||
|
||||
ManagedString _(ManagedString s1, ManagedString s2) {
|
||||
return concat(s1, s2);
|
||||
}
|
||||
|
||||
ManagedString substring(ManagedString s, int start, int len) {
|
||||
if (!in_range(s, start) || len < start || len < 0)
|
||||
return ManagedString::EmptyString;
|
||||
|
||||
return s.substring(start, len);
|
||||
}
|
||||
|
||||
bool equals(ManagedString s1, ManagedString s2) {
|
||||
return s1 == s2;
|
||||
}
|
||||
|
||||
int count(ManagedString s) {
|
||||
return s.length();
|
||||
}
|
||||
|
||||
ManagedString at(ManagedString s, int i) {
|
||||
if (!in_range(s, i))
|
||||
return ManagedString::EmptyString;
|
||||
|
||||
return ManagedString(s.charAt(i));
|
||||
}
|
||||
|
||||
int to_character_code(ManagedString s) {
|
||||
return s.length() > 0 ? s.charAt(0) : '\0';
|
||||
}
|
||||
|
||||
int code_at(ManagedString s, int i) {
|
||||
return in_range(s, i) ? s.charAt(i) : '\0';
|
||||
}
|
||||
|
||||
int to_number(ManagedString s) {
|
||||
return atoi(s.toCharArray());
|
||||
}
|
||||
|
||||
void post_to_wall(ManagedString s) {
|
||||
uBit.serial.printf("%s\r\n", s.toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
namespace math {
|
||||
int max(int x, int y) { return x < y ? y : x; }
|
||||
int min(int x, int y) { return x < y ? x : y; }
|
||||
int random(int max) {
|
||||
if (max == INT_MIN)
|
||||
return -uBit.random(INT_MAX);
|
||||
else if (max < 0)
|
||||
return -uBit.random(-max);
|
||||
else if (max == 0)
|
||||
return 0;
|
||||
else
|
||||
return uBit.random(max);
|
||||
}
|
||||
// Unspecified behavior for int_min
|
||||
int abs(int x) { return x < 0 ? -x : x; }
|
||||
int mod (int x, int y) { return x % y; }
|
||||
|
||||
int pow(int x, int n) {
|
||||
if (n < 0)
|
||||
return 0;
|
||||
int r = 1;
|
||||
while (n) {
|
||||
if (n & 1)
|
||||
r *= x;
|
||||
n >>= 1;
|
||||
x *= x;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int clamp(int l, int h, int x) {
|
||||
return x < l ? l : x > h ? h : x;
|
||||
}
|
||||
|
||||
int sqrt(int x) {
|
||||
return ::sqrt(x);
|
||||
}
|
||||
|
||||
int sign(int x) {
|
||||
return x > 0 ? 1 : (x == 0 ? 0 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
namespace number {
|
||||
bool lt(int x, int y) { return x < y; }
|
||||
bool le(int x, int y) { return x <= y; }
|
||||
bool neq(int x, int y) { return x != y; }
|
||||
bool eq(int x, int y) { return x == y; }
|
||||
bool gt(int x, int y) { return x > y; }
|
||||
bool ge(int x, int y) { return x >= y; }
|
||||
int add(int x, int y) { return x + y; }
|
||||
int subtract(int x, int y) { return x - y; }
|
||||
int divide(int x, int y) { return x / y; }
|
||||
int multiply(int x, int y) { return x * y; }
|
||||
ManagedString to_string(int x) { return ManagedString(x); }
|
||||
ManagedString to_character(int x) { return ManagedString((char) x); }
|
||||
void post_to_wall(int s) {
|
||||
uBit.serial.printf("%d\r\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
namespace bits {
|
||||
|
||||
// See http://blog.regehr.org/archives/1063
|
||||
uint32_t rotl32c (uint32_t x, uint32_t n)
|
||||
{
|
||||
return (x<<n) | (x>>(-n&31));
|
||||
}
|
||||
|
||||
int or_uint32(int x, int y) { return (uint32_t) x | (uint32_t) y; }
|
||||
int and_uint32(int x, int y) { return (uint32_t) x & (uint32_t) y; }
|
||||
int xor_uint32(int x, int y) { return (uint32_t) x ^ (uint32_t) y; }
|
||||
int shift_left_uint32(int x, int y) { return (uint32_t) x << y; }
|
||||
int shift_right_uint32(int x, int y) { return (uint32_t) x >> y; }
|
||||
int rotate_right_uint32(int x, int y) { return rotl32c((uint32_t) x, 32-y); }
|
||||
int rotate_left_uint32(int x, int y) { return rotl32c((uint32_t) x, y); }
|
||||
}
|
||||
|
||||
namespace boolean {
|
||||
bool or_(bool x, bool y) { return x || y; }
|
||||
bool and_(bool x, bool y) { return x && y; }
|
||||
bool not_(bool x) { return !x; }
|
||||
bool equals(bool x, bool y) { return x == y; }
|
||||
ManagedString to_string(bool x) {
|
||||
return x ? ManagedString("true") : ManagedString("false");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implementation of the BBC micro:bit features
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace micro_bit {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Radio
|
||||
// -------------------------------------------------------------------------
|
||||
uint8_t radioDefaultGroup = MICROBIT_RADIO_DEFAULT_GROUP;
|
||||
bool radioEnabled = false;
|
||||
int datagramBuf[4];
|
||||
int datagramRSSI = -1;
|
||||
|
||||
int radioEnable() {
|
||||
int r = uBit.radio.enable();
|
||||
if (r != MICROBIT_OK) return r;
|
||||
if (!radioEnabled) {
|
||||
if (radioDefaultGroup != MICROBIT_RADIO_DEFAULT_GROUP) {
|
||||
uBit.radio.setGroup(radioDefaultGroup);
|
||||
}
|
||||
memset(datagramBuf, 4, 0);
|
||||
radioEnabled = true;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void setGroup(int id) {
|
||||
if (radioEnable() != MICROBIT_OK) return;
|
||||
uBit.radio.setGroup(id);
|
||||
}
|
||||
|
||||
void setTransmitPower(int power) {
|
||||
if (radioEnable() != MICROBIT_OK) return;
|
||||
uBit.radio.setTransmitPower(power);
|
||||
}
|
||||
|
||||
void broadcastMessage(int message) {
|
||||
if (radioEnable() != MICROBIT_OK) return;
|
||||
|
||||
uBit.radio.event.eventReceived(MicroBitEvent(MES_BROADCAST_GENERAL_ID, message, CREATE_ONLY));
|
||||
}
|
||||
|
||||
void onBroadcastMessageReceived(int message, function<void()> f) {
|
||||
if (radioEnable() != MICROBIT_OK) return;
|
||||
|
||||
registerWithDal(MES_BROADCAST_GENERAL_ID, message, f);
|
||||
}
|
||||
|
||||
void datagramSendNumber(int value) {
|
||||
datagramSendNumbers(value, 0, 0, 0);
|
||||
}
|
||||
|
||||
void datagramSendNumbers(int value0, int value1, int value2, int value3) {
|
||||
if (radioEnable() != MICROBIT_OK) return;
|
||||
|
||||
datagramBuf[0] = value0;
|
||||
datagramBuf[1] = value1;
|
||||
datagramBuf[2] = value2;
|
||||
datagramBuf[3] = value3;
|
||||
uBit.radio.datagram.send((uint8_t*)datagramBuf, 16);
|
||||
memset(datagramBuf, 4, 0);
|
||||
}
|
||||
|
||||
int datagramReceiveNumber() {
|
||||
if (radioEnable() != MICROBIT_OK) return 0;
|
||||
|
||||
memset(datagramBuf, 4, 0);
|
||||
|
||||
PacketBuffer packet = uBit.radio.datagram.recv();
|
||||
uint8_t* buf = (uint8_t*)datagramBuf;
|
||||
int n = min(16, packet.length());
|
||||
for(int i = 0;i<n;++i)
|
||||
buf[i] = packet[i];
|
||||
datagramRSSI = packet.getRSSI();
|
||||
|
||||
return datagramBuf[0];
|
||||
}
|
||||
|
||||
int datagramGetNumber(int index) {
|
||||
if (radioEnable() != MICROBIT_OK) return 0;
|
||||
if (index < 0 || index >= 4) return 0;
|
||||
return datagramBuf[index];
|
||||
}
|
||||
|
||||
int datagramGetRSSI() {
|
||||
if (radioEnable() != MICROBIT_OK) return 0;
|
||||
|
||||
return datagramRSSI;
|
||||
}
|
||||
|
||||
void onDatagramReceived(function<void()> f) {
|
||||
if (radioEnable() != MICROBIT_OK) return;
|
||||
|
||||
registerWithDal(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, f);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Gestures
|
||||
// -------------------------------------------------------------------------
|
||||
void onGesture(int gesture, function<void()> f) {
|
||||
if (gesture == GESTURE_8G || gesture == GESTURE_6G)
|
||||
uBit.accelerometer.setRange(8);
|
||||
else if (gesture == GESTURE_3G)
|
||||
uBit.accelerometer.setRange(4);
|
||||
registerWithDal(MICROBIT_ID_GESTURE, gesture, f);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Sensors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
int compassHeading() {
|
||||
return uBit.compass.heading();
|
||||
}
|
||||
|
||||
int lightLevel() {
|
||||
return uBit.display.readLightLevel();
|
||||
}
|
||||
|
||||
int temperature() {
|
||||
return uBit.thermometer.getTemperature();
|
||||
}
|
||||
|
||||
int getMagneticForce(int dimension) {
|
||||
if (!uBit.compass.isCalibrated())
|
||||
uBit.compass.calibrate();
|
||||
if (dimension == 0)
|
||||
return uBit.compass.getX() / 1000;
|
||||
else if (dimension == 1)
|
||||
return uBit.compass.getY() / 1000;
|
||||
else if (dimension == 2)
|
||||
return uBit.compass.getZ() / 1000;
|
||||
else if (dimension == 3)
|
||||
return uBit.compass.getFieldStrength() / 1000;
|
||||
// unknown
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int getAccelerationStrength() {
|
||||
double x = uBit.accelerometer.getX();
|
||||
double y = uBit.accelerometer.getY();
|
||||
double z = uBit.accelerometer.getZ();
|
||||
return (int)sqrt(x*x+y*y+z*z);
|
||||
}
|
||||
|
||||
int getAcceleration(int dimension) {
|
||||
if (dimension == 0)
|
||||
return uBit.accelerometer.getX();
|
||||
else if (dimension == 1)
|
||||
return uBit.accelerometer.getY();
|
||||
else if (dimension == 2)
|
||||
return uBit.accelerometer.getZ();
|
||||
else if (dimension == 3)
|
||||
return getAccelerationStrength();
|
||||
// unknown
|
||||
else return 0;
|
||||
}
|
||||
|
||||
void setAccelerometerRange(int range) {
|
||||
uBit.accelerometer.setRange(range);
|
||||
}
|
||||
|
||||
int getRotation(int dimension) {
|
||||
if (dimension == 0)
|
||||
return uBit.accelerometer.getPitch();
|
||||
else if (dimension == 1)
|
||||
return uBit.accelerometer.getRoll();
|
||||
// unknown
|
||||
else return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Pins
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// The functions below use the "enum" feature of TouchDevelop, meaning that
|
||||
// the references they are passed are always valid (hence the &-passing).
|
||||
int analogReadPin(MicroBitPin& p) {
|
||||
return p.getAnalogValue();
|
||||
}
|
||||
|
||||
void analogWritePin(MicroBitPin& p, int value) {
|
||||
p.setAnalogValue(value);
|
||||
}
|
||||
|
||||
void setAnalogPeriodUs(MicroBitPin& p, int micros) {
|
||||
p.setAnalogPeriodUs(micros);
|
||||
}
|
||||
|
||||
void servoWritePin(MicroBitPin& p, int value) {
|
||||
p.setServoValue(value);
|
||||
}
|
||||
|
||||
void setServoPulseUs(MicroBitPin& p, int micros) {
|
||||
p.setServoPulseUs(micros);
|
||||
}
|
||||
|
||||
int digitalReadPin(MicroBitPin& p) {
|
||||
return p.getDigitalValue();
|
||||
}
|
||||
|
||||
void digitalWritePin(MicroBitPin& p, int value) {
|
||||
p.setDigitalValue(value);
|
||||
}
|
||||
|
||||
bool isPinTouched(MicroBitPin& pin) {
|
||||
return pin.isTouched();
|
||||
}
|
||||
|
||||
void onPinPressed(int pin, function<void()> f) {
|
||||
if (f != NULL) {
|
||||
// Forces the PIN to switch to makey-makey style detection.
|
||||
switch (pin) {
|
||||
case MICROBIT_ID_IO_P0:
|
||||
uBit.io.P0.isTouched();
|
||||
break;
|
||||
case MICROBIT_ID_IO_P1:
|
||||
uBit.io.P1.isTouched();
|
||||
break;
|
||||
case MICROBIT_ID_IO_P2:
|
||||
uBit.io.P2.isTouched();
|
||||
break;
|
||||
}
|
||||
onButtonPressed(pin, f);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Buttons
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
bool isButtonPressed(int button) {
|
||||
if (button == MICROBIT_ID_BUTTON_A)
|
||||
return uBit.buttonA.isPressed();
|
||||
else if (button == MICROBIT_ID_BUTTON_B)
|
||||
return uBit.buttonB.isPressed();
|
||||
else if (button == MICROBIT_ID_BUTTON_AB)
|
||||
return uBit.buttonAB.isPressed();
|
||||
return false;
|
||||
}
|
||||
|
||||
void onButtonPressedExt(int button, int event, function<void()> f) {
|
||||
registerWithDal(button, event, f);
|
||||
}
|
||||
|
||||
void onButtonPressed(int button, function<void()> f) {
|
||||
onButtonPressedExt(button, MICROBIT_BUTTON_EVT_CLICK, f);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// System
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void fun_helper(function<void()>* f) {
|
||||
(*f)();
|
||||
}
|
||||
|
||||
void fun_delete_helper(function<void()>* f) {
|
||||
// The fiber is done, so release associated resources and free the
|
||||
// heap-allocated closure.
|
||||
delete f;
|
||||
release_fiber();
|
||||
}
|
||||
|
||||
void forever_helper(function<void()>* f) {
|
||||
while (true) {
|
||||
(*f)();
|
||||
pause(20);
|
||||
}
|
||||
}
|
||||
|
||||
void runInBackground(function<void()> f) {
|
||||
if (f) {
|
||||
// The API provided by the DAL only offers a low-level, C-style,
|
||||
// void*-based callback structure. Therefore, allocate the closure on
|
||||
// the heap to make sure it fits in one word.
|
||||
auto f_allocated = new function<void()>(f);
|
||||
create_fiber((void(*)(void*)) fun_helper, (void*) f_allocated, (void(*)(void*)) fun_delete_helper);
|
||||
}
|
||||
}
|
||||
|
||||
void pause(int ms) {
|
||||
uBit.sleep(ms);
|
||||
}
|
||||
|
||||
void forever(function<void()> f) {
|
||||
if (f) {
|
||||
auto f_allocated = new function<void()>(f);
|
||||
create_fiber((void(*)(void*)) forever_helper, (void*) f_allocated, (void(*)(void*)) fun_delete_helper);
|
||||
}
|
||||
}
|
||||
|
||||
int getCurrentTime() {
|
||||
return uBit.systemTime();
|
||||
}
|
||||
|
||||
// These functions are exposed via the "micro:bit extras" library. They are
|
||||
// simplified; for any serious hardware, write the i2c communication thing
|
||||
// in C++.
|
||||
|
||||
int i2c_read(int addr) {
|
||||
char c;
|
||||
uBit.i2c.read(addr << 1, &c, 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
void i2c_write(int addr, char c) {
|
||||
uBit.i2c.write(addr << 1, &c, 1);
|
||||
}
|
||||
|
||||
void i2c_write2(int addr, int c1, int c2) {
|
||||
char c[2];
|
||||
c[0] = (char) c1;
|
||||
c[1] = (char) c2;
|
||||
uBit.i2c.write(addr << 1, c, 2);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Screen (reading/modifying the global, mutable state of the display)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Closed interval.
|
||||
inline bool in_range(int x, int l, int h) {
|
||||
return l <= x && x <= h;
|
||||
}
|
||||
|
||||
int getBrightness() {
|
||||
return uBit.display.getBrightness();
|
||||
}
|
||||
|
||||
void setBrightness(int v) {
|
||||
if (in_range(v, 0, 255))
|
||||
uBit.display.setBrightness(v);
|
||||
}
|
||||
|
||||
void setDisplayMode(int mode) {
|
||||
uBit.display.setDisplayMode((DisplayMode)mode);
|
||||
}
|
||||
|
||||
void clearScreen() {
|
||||
uBit.display.image.clear();
|
||||
}
|
||||
|
||||
void plot(int x, int y) {
|
||||
uBit.display.image.setPixelValue(x, y, 1);
|
||||
}
|
||||
|
||||
void unPlot(int x, int y) {
|
||||
uBit.display.image.setPixelValue(x, y, 0);
|
||||
}
|
||||
|
||||
bool point(int x, int y) {
|
||||
return getImagePixel(uBit.display.image, x, y);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Images (helpers that create/modify a MicroBitImage)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Argument rewritten by the C++ emitter to be what we need
|
||||
MicroBitImage createImage(int w, int h, const uint8_t* bitmap) {
|
||||
return MicroBitImage(w, h, bitmap);
|
||||
}
|
||||
|
||||
MicroBitImage createImageFromString(ManagedString s) {
|
||||
const char* raw = s.toCharArray();
|
||||
return MicroBitImage(raw);
|
||||
}
|
||||
|
||||
void clearImage(MicroBitImage i) {
|
||||
i.clear();
|
||||
}
|
||||
|
||||
int getImagePixel(MicroBitImage i, int x, int y) {
|
||||
int pix = i.getPixelValue(x, y);
|
||||
if (pix < 0) // out of range
|
||||
return 0;
|
||||
else
|
||||
return pix;
|
||||
}
|
||||
|
||||
void setImagePixel(MicroBitImage i, int x, int y, int value) {
|
||||
// DAL does range checking
|
||||
i.setPixelValue(x, y, value);
|
||||
}
|
||||
|
||||
int getImageWidth(MicroBitImage i) {
|
||||
return i.getWidth();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Various "show"-style functions to display and scroll things on the screen
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void showLetter(ManagedString s) {
|
||||
uBit.display.print(s.charAt(0));
|
||||
}
|
||||
|
||||
void showDigit(int n) {
|
||||
uBit.display.print('0' + (n % 10));
|
||||
}
|
||||
|
||||
void scrollNumber(int n, int delay) {
|
||||
if (delay < 0)
|
||||
return;
|
||||
|
||||
ManagedString t(n);
|
||||
if (n < 0 || n >= 10) {
|
||||
uBit.display.scroll(t, delay);
|
||||
} else {
|
||||
uBit.display.print(t.charAt(0), delay * 5);
|
||||
}
|
||||
}
|
||||
|
||||
void scrollString(ManagedString s, int delay) {
|
||||
if (delay < 0)
|
||||
return;
|
||||
|
||||
int l = s.length();
|
||||
if (l == 0) {
|
||||
uBit.display.clear();
|
||||
uBit.sleep(delay * 5);
|
||||
} else if (l > 1) {
|
||||
uBit.display.scroll(s, delay);
|
||||
} else {
|
||||
uBit.display.print(s.charAt(0), delay * 5);
|
||||
}
|
||||
}
|
||||
|
||||
void plotImage(MicroBitImage i, int offset) {
|
||||
uBit.display.print(i, -offset, 0, 0, 0);
|
||||
}
|
||||
|
||||
void plotLeds(int w, int h, const uint8_t* bitmap) {
|
||||
plotImage(MicroBitImage(w, h, bitmap), 0);
|
||||
}
|
||||
|
||||
void showImage(MicroBitImage i, int offset) {
|
||||
uBit.display.print(i, -offset, 0, 0);
|
||||
}
|
||||
|
||||
// These have their arguments rewritten by the C++ compiler.
|
||||
void showLeds(int w, int h, const uint8_t* bitmap, int delay) {
|
||||
uBit.display.print(MicroBitImage(w, h, bitmap), 0, 0, 0, delay);
|
||||
}
|
||||
|
||||
void scrollImage(MicroBitImage i, int offset, int delay) {
|
||||
if (i.getWidth() <= 5)
|
||||
showImage(i, 0);
|
||||
else
|
||||
uBit.display.animate(i, delay, offset, 0);
|
||||
}
|
||||
|
||||
void showAnimation(int w, int h, const uint8_t* bitmap, int ms) {
|
||||
uBit.display.animate(MicroBitImage(w, h, bitmap), ms, 5, 0);
|
||||
}
|
||||
|
||||
void stopAnimation() {
|
||||
uBit.display.stopAnimation();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// BLE Events
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void generate_event(int id, int event) {
|
||||
MicroBitEvent e(id, event);
|
||||
}
|
||||
|
||||
void on_event(int id, function<void(int)> f) {
|
||||
registerWithDal(id, MICROBIT_EVT_ANY, f);
|
||||
}
|
||||
|
||||
void onDeviceInfo(int event, function<void()> f) {
|
||||
registerWithDal(MES_DEVICE_INFO_ID, event, f);
|
||||
}
|
||||
|
||||
int _signalStrength = -1;
|
||||
void initSignalStrength() {
|
||||
if (_signalStrength < 0) {
|
||||
_signalStrength = 0;
|
||||
uBit.MessageBus.listen(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, signalStrengthHandler);
|
||||
}
|
||||
}
|
||||
|
||||
int signalStrength() {
|
||||
initSignalStrength();
|
||||
return _signalStrength;
|
||||
}
|
||||
|
||||
void signalStrengthHandler(MicroBitEvent ev) {
|
||||
// keep in sync with MESEvents.h
|
||||
_signalStrength = ev.value - 1;
|
||||
}
|
||||
|
||||
void onSignalStrengthChanged(function<void()> f) {
|
||||
initSignalStrength();
|
||||
registerWithDal(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, f);
|
||||
}
|
||||
|
||||
void onGamepadButton(int id, function<void()> a) {
|
||||
registerWithDal(MES_DPAD_CONTROLLER_ID, id, a);
|
||||
}
|
||||
|
||||
|
||||
namespace devices {
|
||||
void remote_control(int event) {
|
||||
micro_bit::generate_event(MES_REMOTE_CONTROL_ID,event);
|
||||
}
|
||||
void camera(int event) {
|
||||
micro_bit::generate_event(MES_CAMERA_ID, event);
|
||||
}
|
||||
void alert(int event) {
|
||||
micro_bit::generate_event(MES_ALERTS_ID, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Music
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
MicroBitPin* pitchPin = NULL;
|
||||
|
||||
void enablePitch(MicroBitPin& p) {
|
||||
pitchPin = &p;
|
||||
}
|
||||
|
||||
void pitch(int freq, int ms) {
|
||||
if (pitchPin == NULL) return;
|
||||
if (freq <= 0) {
|
||||
pitchPin->setAnalogValue(0);
|
||||
} else {
|
||||
pitchPin->setAnalogValue(512);
|
||||
pitchPin->setAnalogPeriodUs(1000000/freq);
|
||||
}
|
||||
|
||||
if (ms > 0) {
|
||||
uBit.sleep(ms);
|
||||
pitchPin->setAnalogValue(0);
|
||||
wait_ms(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Called at start-up by the generated code (currently not enabled).
|
||||
// -------------------------------------------------------------------------
|
||||
void internal_main() {
|
||||
}
|
||||
}
|
||||
|
||||
// vim: set ts=2 sw=2 sts=2:
|
876
source/bitvm.cpp
876
source/bitvm.cpp
|
@ -1,876 +0,0 @@
|
|||
#include "BitVM.h"
|
||||
#include "MicroBitTouchDevelop.h"
|
||||
#include <cstdlib>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#define DBG printf
|
||||
//#define DBG(...)
|
||||
|
||||
// Macros to reference function pointer in the jump-list
|
||||
// c in mbitc - stands for 'common'
|
||||
#define mbit(x) (void*)bitvm_micro_bit::x,
|
||||
#define mbitc(x) (void*)micro_bit::x,
|
||||
|
||||
namespace bitvm {
|
||||
uint16_t *bytecode;
|
||||
|
||||
uint32_t ldloc(RefLocal *r)
|
||||
{
|
||||
return r->v;
|
||||
}
|
||||
|
||||
uint32_t ldlocRef(RefRefLocal *r)
|
||||
{
|
||||
uint32_t tmp = r->v;
|
||||
incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void stloc(RefLocal *r, uint32_t v)
|
||||
{
|
||||
r->v = v;
|
||||
}
|
||||
|
||||
void stlocRef(RefRefLocal *r, uint32_t v)
|
||||
{
|
||||
decr(r->v);
|
||||
r->v = v;
|
||||
}
|
||||
|
||||
RefLocal *mkloc()
|
||||
{
|
||||
return new RefLocal();
|
||||
}
|
||||
|
||||
RefRefLocal *mklocRef()
|
||||
{
|
||||
return new RefRefLocal();
|
||||
}
|
||||
|
||||
// All of the functions below unref() self. This is for performance reasons -
|
||||
// the code emitter will not emit the unrefs for them.
|
||||
|
||||
uint32_t ldfld(RefRecord *r, int idx)
|
||||
{
|
||||
auto tmp = r->ld(idx);
|
||||
r->unref();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
uint32_t ldfldRef(RefRecord *r, int idx)
|
||||
{
|
||||
auto tmp = r->ldref(idx);
|
||||
r->unref();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void stfld(RefRecord *r, int idx, uint32_t val)
|
||||
{
|
||||
r->st(idx, val);
|
||||
r->unref();
|
||||
}
|
||||
|
||||
void stfldRef(RefRecord *r, int idx, uint32_t val)
|
||||
{
|
||||
r->stref(idx, val);
|
||||
r->unref();
|
||||
}
|
||||
|
||||
uint32_t ldglb(int idx)
|
||||
{
|
||||
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
|
||||
return globals[idx];
|
||||
}
|
||||
|
||||
uint32_t ldglbRef(int idx)
|
||||
{
|
||||
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
|
||||
uint32_t tmp = globals[idx];
|
||||
incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
uint32_t is_invalid(uint32_t v)
|
||||
{
|
||||
return v == 0;
|
||||
}
|
||||
|
||||
// note the idx comes last - it's more convenient that way in the emitter
|
||||
void stglb(uint32_t v, int idx)
|
||||
{
|
||||
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
|
||||
globals[idx] = v;
|
||||
}
|
||||
|
||||
void stglbRef(uint32_t v, int idx)
|
||||
{
|
||||
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
|
||||
decr(globals[idx]);
|
||||
globals[idx] = v;
|
||||
}
|
||||
|
||||
// Store a captured local in a closure. It returns the action, so it can be chained.
|
||||
RefAction *stclo(RefAction *a, int idx, uint32_t v)
|
||||
{
|
||||
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
|
||||
a->st(idx, v);
|
||||
return a;
|
||||
}
|
||||
|
||||
// This one is used for testing in 'bitvm test0'
|
||||
uint32_t const3() { return 3; }
|
||||
|
||||
#ifdef DEBUG_MEMLEAKS
|
||||
std::set<RefObject*> allptrs;
|
||||
void debugMemLeaks()
|
||||
{
|
||||
printf("LIVE POINTERS:\n");
|
||||
for(std::set<RefObject*>::iterator itr = allptrs.begin();itr!=allptrs.end();itr++)
|
||||
{
|
||||
(*itr)->print();
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
void debugMemLeaks() {}
|
||||
#endif
|
||||
|
||||
namespace bitvm_number {
|
||||
void post_to_wall(int n) { printf("%d\n", n); }
|
||||
|
||||
StringData *to_character(int x)
|
||||
{
|
||||
return ManagedString((char)x).leakData();
|
||||
}
|
||||
|
||||
StringData *to_string(int x)
|
||||
{
|
||||
return ManagedString(x).leakData();
|
||||
}
|
||||
}
|
||||
|
||||
namespace contract {
|
||||
void assert(int cond, uint32_t msg)
|
||||
{
|
||||
if (cond == 0) {
|
||||
printf("Assertion failed: %s\n", getstr(msg));
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace string {
|
||||
StringData *mkEmpty()
|
||||
{
|
||||
return ManagedString::EmptyString.leakData();
|
||||
}
|
||||
|
||||
StringData *concat(StringData *s1, StringData *s2) {
|
||||
ManagedString a(s1), b(s2);
|
||||
return (a + b).leakData();
|
||||
}
|
||||
|
||||
StringData *concat_op(StringData *s1, StringData *s2) {
|
||||
return concat(s1, s2);
|
||||
}
|
||||
|
||||
StringData *substring(StringData *s, int i, int j) {
|
||||
return (ManagedString(s).substring(i, j)).leakData();
|
||||
}
|
||||
|
||||
bool equals(StringData *s1, StringData *s2) {
|
||||
return ManagedString(s1) == ManagedString(s2);
|
||||
}
|
||||
|
||||
int count(StringData *s) {
|
||||
return s->len;
|
||||
}
|
||||
|
||||
StringData *at(StringData *s, int i) {
|
||||
return ManagedString((char)ManagedString(s).charAt(i)).leakData();
|
||||
}
|
||||
|
||||
int to_character_code(StringData *s) {
|
||||
return ManagedString(s).charAt(0);
|
||||
}
|
||||
|
||||
int code_at(StringData *s, int i) {
|
||||
return ManagedString(s).charAt(i);
|
||||
}
|
||||
|
||||
int to_number(StringData *s) {
|
||||
return atoi(s->data);
|
||||
}
|
||||
|
||||
void post_to_wall(StringData *s) { printf("%s\n", s->data); }
|
||||
}
|
||||
|
||||
namespace bitvm_boolean {
|
||||
// Cache the string literals "true" and "false" when used.
|
||||
// Note that the representation of booleans stays the usual C-one.
|
||||
|
||||
static const char sTrue[] __attribute__ ((aligned (4))) = "\xff\xff\x04\x00" "true\0";
|
||||
static const char sFalse[] __attribute__ ((aligned (4))) = "\xff\xff\x05\x00" "false\0";
|
||||
|
||||
StringData *to_string(int v)
|
||||
{
|
||||
if (v) {
|
||||
return (StringData*)(void*)sTrue;
|
||||
} else {
|
||||
return (StringData*)(void*)sFalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringData *mkStringData(uint32_t len)
|
||||
{
|
||||
StringData *r = (StringData*)malloc(sizeof(StringData)+len+1);
|
||||
r->init();
|
||||
r->len = len;
|
||||
memset(r->data, '\0', len + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
// The proper StringData* representation is already laid out in memory by the code generator.
|
||||
uint32_t stringData(uint32_t lit)
|
||||
{
|
||||
return (uint32_t)getstr(lit);
|
||||
}
|
||||
|
||||
|
||||
namespace collection {
|
||||
|
||||
RefCollection *mk(uint32_t flags)
|
||||
{
|
||||
RefCollection *r = new RefCollection(flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
int count(RefCollection *c) { return c->data.size(); }
|
||||
|
||||
void add(RefCollection *c, uint32_t x) {
|
||||
if (c->flags & 1) incr(x);
|
||||
c->data.push_back(x);
|
||||
}
|
||||
|
||||
inline bool in_range(RefCollection *c, int x) {
|
||||
return (0 <= x && x < (int)c->data.size());
|
||||
}
|
||||
|
||||
uint32_t at(RefCollection *c, int x) {
|
||||
if (in_range(c, x)) {
|
||||
uint32_t tmp = c->data.at(x);
|
||||
if (c->flags & 1) incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
else {
|
||||
error(ERR_OUT_OF_BOUNDS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_at(RefCollection *c, int x) {
|
||||
if (!in_range(c, x))
|
||||
return;
|
||||
|
||||
if (c->flags & 1) decr(c->data.at(x));
|
||||
c->data.erase(c->data.begin()+x);
|
||||
}
|
||||
|
||||
void set_at(RefCollection *c, int x, uint32_t y) {
|
||||
if (!in_range(c, x))
|
||||
return;
|
||||
|
||||
if (c->flags & 1) {
|
||||
decr(c->data.at(x));
|
||||
incr(y);
|
||||
}
|
||||
c->data.at(x) = y;
|
||||
}
|
||||
|
||||
int index_of(RefCollection *c, uint32_t x, int start) {
|
||||
if (!in_range(c, start))
|
||||
return -1;
|
||||
|
||||
if (c->flags & 2) {
|
||||
StringData *xx = (StringData*)x;
|
||||
for (uint32_t i = start; i < c->data.size(); ++i) {
|
||||
StringData *ee = (StringData*)c->data.at(i);
|
||||
if (xx->len == ee->len && memcmp(xx->data, ee->data, xx->len) == 0)
|
||||
return (int)i;
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = start; i < c->data.size(); ++i)
|
||||
if (c->data.at(i) == x)
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int remove(RefCollection *c, uint32_t x) {
|
||||
int idx = index_of(c, x, 0);
|
||||
if (idx >= 0) {
|
||||
remove_at(c, idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace buffer {
|
||||
|
||||
RefBuffer *mk(uint32_t size)
|
||||
{
|
||||
RefBuffer *r = new RefBuffer();
|
||||
r->data.resize(size);
|
||||
return r;
|
||||
}
|
||||
|
||||
char *cptr(RefBuffer *c)
|
||||
{
|
||||
return (char*)&c->data[0];
|
||||
}
|
||||
|
||||
int count(RefBuffer *c) { return c->data.size(); }
|
||||
|
||||
void fill(RefBuffer *c, int v)
|
||||
{
|
||||
memset(cptr(c), v, count(c));
|
||||
}
|
||||
|
||||
void fill_random(RefBuffer *c)
|
||||
{
|
||||
int len = count(c);
|
||||
for (int i = 0; i < len; ++i)
|
||||
c->data[i] = uBit.random(0x100);
|
||||
}
|
||||
|
||||
void add(RefBuffer *c, uint32_t x) {
|
||||
c->data.push_back(x);
|
||||
}
|
||||
|
||||
inline bool in_range(RefBuffer *c, int x) {
|
||||
return (0 <= x && x < (int)c->data.size());
|
||||
}
|
||||
|
||||
uint32_t at(RefBuffer *c, int x) {
|
||||
if (in_range(c, x)) {
|
||||
return c->data[x];
|
||||
}
|
||||
else {
|
||||
error(ERR_OUT_OF_BOUNDS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set(RefBuffer *c, int x, uint32_t y) {
|
||||
if (!in_range(c, x))
|
||||
return;
|
||||
c->data[x] = y;
|
||||
}
|
||||
}
|
||||
|
||||
namespace bitvm_bits {
|
||||
RefBuffer *create_buffer(int size)
|
||||
{
|
||||
return buffer::mk(size);
|
||||
}
|
||||
}
|
||||
|
||||
namespace record {
|
||||
RefRecord* mk(int reflen, int totallen)
|
||||
{
|
||||
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
|
||||
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
|
||||
|
||||
void *ptr = ::operator new(sizeof(RefRecord) + totallen * sizeof(uint32_t));
|
||||
RefRecord *r = new (ptr) RefRecord();
|
||||
r->len = totallen;
|
||||
r->reflen = reflen;
|
||||
memset(r->fields, 0, r->len * sizeof(uint32_t));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
namespace action {
|
||||
Action mk(int reflen, int totallen, int startptr)
|
||||
{
|
||||
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
|
||||
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
|
||||
check(bytecode[startptr] == 0xffff, ERR_INVALID_BINARY_HEADER, 3);
|
||||
check(bytecode[startptr + 1] == 0, ERR_INVALID_BINARY_HEADER, 4);
|
||||
|
||||
|
||||
uint32_t tmp = (uint32_t)&bytecode[startptr];
|
||||
|
||||
if (totallen == 0) {
|
||||
return tmp; // no closure needed
|
||||
}
|
||||
|
||||
void *ptr = ::operator new(sizeof(RefAction) + totallen * sizeof(uint32_t));
|
||||
RefAction *r = new (ptr) RefAction();
|
||||
r->len = totallen;
|
||||
r->reflen = reflen;
|
||||
r->func = (ActionCB)((tmp + 4) | 1);
|
||||
memset(r->fields, 0, r->len * sizeof(uint32_t));
|
||||
|
||||
return (Action)r;
|
||||
}
|
||||
|
||||
void run1(Action a, int arg)
|
||||
{
|
||||
if (hasVTable(a))
|
||||
((RefAction*)a)->run(arg);
|
||||
else {
|
||||
check(*(uint16_t*)a == 0xffff, ERR_INVALID_BINARY_HEADER, 4);
|
||||
((ActionCB)((a + 4) | 1))(NULL, NULL, arg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(Action a)
|
||||
{
|
||||
action::run1(a, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implementation of the BBC micro:bit features
|
||||
// ---------------------------------------------------------------------------
|
||||
using namespace touch_develop;
|
||||
|
||||
namespace bitvm_micro_bit {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// An adapter for the API expected by the run-time.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
map<pair<int, int>, Action> handlersMap;
|
||||
|
||||
// We have the invariant that if [dispatchEvent] is registered against the DAL
|
||||
// for a given event, then [handlersMap] contains a valid entry for that
|
||||
// event.
|
||||
void dispatchEvent(MicroBitEvent e) {
|
||||
Action curr = handlersMap[{ e.source, e.value }];
|
||||
if (curr)
|
||||
action::run(curr);
|
||||
|
||||
curr = handlersMap[{ e.source, MICROBIT_EVT_ANY }];
|
||||
if (curr)
|
||||
action::run1(curr, e.value);
|
||||
}
|
||||
|
||||
void registerWithDal(int id, int event, Action a) {
|
||||
Action prev = handlersMap[{ id, event }];
|
||||
if (prev)
|
||||
decr(prev);
|
||||
else
|
||||
uBit.MessageBus.listen(id, event, dispatchEvent);
|
||||
incr(a);
|
||||
handlersMap[{ id, event }] = a;
|
||||
}
|
||||
|
||||
void on_event(int id, Action a) {
|
||||
if (a != 0) {
|
||||
registerWithDal(id, MICROBIT_EVT_ANY, a);
|
||||
}
|
||||
}
|
||||
|
||||
void onDeviceInfo(int event, Action a) {
|
||||
if (a != 0) {
|
||||
registerWithDal(MES_DEVICE_INFO_ID, event, a);
|
||||
}
|
||||
}
|
||||
|
||||
void onSignalStrengthChanged(Action a) {
|
||||
if (a != 0) {
|
||||
::touch_develop::micro_bit::initSignalStrength();
|
||||
registerWithDal(MES_SIGNAL_STRENGTH_ID, MICROBIT_EVT_ANY, a);
|
||||
}
|
||||
}
|
||||
|
||||
void onGamepadButton(int id, Action a) {
|
||||
if (a != 0) {
|
||||
registerWithDal(MES_DPAD_CONTROLLER_ID, id, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Pins
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void onPinPressed(int pin, Action a) {
|
||||
if (a != 0) {
|
||||
// Forces the PIN to switch to makey-makey style detection.
|
||||
switch(pin) {
|
||||
case MICROBIT_ID_IO_P0:
|
||||
uBit.io.P0.isTouched();
|
||||
break;
|
||||
case MICROBIT_ID_IO_P1:
|
||||
uBit.io.P1.isTouched();
|
||||
break;
|
||||
case MICROBIT_ID_IO_P2:
|
||||
uBit.io.P2.isTouched();
|
||||
break;
|
||||
}
|
||||
registerWithDal(pin, MICROBIT_BUTTON_EVT_CLICK, a);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Radio
|
||||
// -------------------------------------------------------------------------
|
||||
void onBroadcastMessageReceived(int message, Action f) {
|
||||
if (::touch_develop::micro_bit::radioEnable() != MICROBIT_OK) return;
|
||||
|
||||
registerWithDal(MES_BROADCAST_GENERAL_ID, message, f);
|
||||
}
|
||||
|
||||
void onDatagramReceived(Action f) {
|
||||
if (f != 0 && ::touch_develop::micro_bit::radioEnable() == MICROBIT_OK) {
|
||||
registerWithDal(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, f);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Gestures
|
||||
// -------------------------------------------------------------------------
|
||||
void onGesture(int gesture, Action f) {
|
||||
registerWithDal(MICROBIT_ID_GESTURE, gesture, f);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Buttons
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void onButtonPressedExt(int button, int event, Action a) {
|
||||
if (a != 0) {
|
||||
registerWithDal(button, event, a);
|
||||
}
|
||||
}
|
||||
|
||||
void onButtonPressed(int button, Action a) {
|
||||
onButtonPressedExt(button, MICROBIT_BUTTON_EVT_CLICK, a);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// System
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void fiberDone(void *a)
|
||||
{
|
||||
decr((Action)a);
|
||||
release_fiber();
|
||||
}
|
||||
|
||||
|
||||
void runInBackground(Action a) {
|
||||
if (a != 0) {
|
||||
incr(a);
|
||||
create_fiber((void(*)(void*))action::run, (void*)a, fiberDone);
|
||||
}
|
||||
}
|
||||
|
||||
void forever_stub(void *a) {
|
||||
while (true) {
|
||||
action::run((Action)a);
|
||||
micro_bit::pause(20);
|
||||
}
|
||||
}
|
||||
|
||||
void forever(Action a) {
|
||||
if (a != 0) {
|
||||
incr(a);
|
||||
create_fiber(forever_stub, (void*)a);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Images (helpers that create/modify a MicroBitImage)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Argument rewritten by the code emitter to be what we need
|
||||
ImageData *createImage(uint32_t lit) {
|
||||
return MicroBitImage(getbytes(lit)).clone().leakData();
|
||||
}
|
||||
|
||||
ImageData *createReadOnlyImage(uint32_t lit) {
|
||||
return getbytes(lit);
|
||||
}
|
||||
|
||||
ImageData *createImageFromString(StringData *s) {
|
||||
return ::touch_develop::micro_bit::createImageFromString(ManagedString(s)).leakData();
|
||||
}
|
||||
|
||||
ImageData *displayScreenShot()
|
||||
{
|
||||
return uBit.display.screenShot().leakData();
|
||||
}
|
||||
|
||||
ImageData *imageClone(ImageData *i)
|
||||
{
|
||||
return MicroBitImage(i).clone().leakData();
|
||||
}
|
||||
|
||||
void clearImage(ImageData *i) {
|
||||
MicroBitImage(i).clear();
|
||||
}
|
||||
|
||||
int getImagePixel(ImageData *i, int x, int y) {
|
||||
int pix = MicroBitImage(i).getPixelValue(x, y);
|
||||
if (pix < 0) return 0;
|
||||
return pix;
|
||||
}
|
||||
|
||||
void setImagePixel(ImageData *i, int x, int y, int value) {
|
||||
MicroBitImage(i).setPixelValue(x, y, value);
|
||||
}
|
||||
|
||||
int getImageHeight(ImageData *i) {
|
||||
return i->height;
|
||||
}
|
||||
|
||||
int getImageWidth(ImageData *i) {
|
||||
return i->width;
|
||||
}
|
||||
|
||||
bool isImageReadOnly(ImageData *i) {
|
||||
return i->isReadOnly();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Various "show"-style functions to display and scroll things on the screen
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void showLetter(StringData *s) {
|
||||
::touch_develop::micro_bit::showLetter(ManagedString(s));
|
||||
}
|
||||
|
||||
void scrollString(StringData *s, int delay) {
|
||||
::touch_develop::micro_bit::scrollString(ManagedString(s), delay);
|
||||
}
|
||||
|
||||
void showImage(ImageData *i, int offset) {
|
||||
::touch_develop::micro_bit::showImage(MicroBitImage(i), offset);
|
||||
}
|
||||
|
||||
void scrollImage(ImageData *i, int offset, int delay) {
|
||||
::touch_develop::micro_bit::scrollImage(MicroBitImage(i), offset, delay);
|
||||
}
|
||||
|
||||
void plotImage(ImageData *i, int offset) {
|
||||
::touch_develop::micro_bit::plotImage(MicroBitImage(i), offset);
|
||||
}
|
||||
|
||||
// [lit] argument is rewritted by code emitted
|
||||
void showLeds(uint32_t lit, int delay) {
|
||||
uBit.display.print(MicroBitImage(getbytes(lit)), 0, 0, 0, delay);
|
||||
}
|
||||
|
||||
void plotLeds(uint32_t lit) {
|
||||
plotImage(getbytes(lit), 0);
|
||||
}
|
||||
|
||||
void showAnimation(uint32_t lit, int ms) {
|
||||
uBit.display.animate(MicroBitImage(getbytes(lit)), ms, 5, 0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Functions that expose member fields of objects because the compilation
|
||||
// scheme only works with the C-style calling convention
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
void reset() { uBit.reset(); }
|
||||
int thermometerGetTemperature() { return uBit.thermometer.getTemperature(); }
|
||||
|
||||
void displayStopAnimation() {
|
||||
uBit.display.stopAnimation();
|
||||
}
|
||||
|
||||
MicroBitPin *ioP0() { return &uBit.io.P0; }
|
||||
MicroBitPin *ioP1() { return &uBit.io.P1; }
|
||||
MicroBitPin *ioP2() { return &uBit.io.P2; }
|
||||
MicroBitPin *ioP3() { return &uBit.io.P3; }
|
||||
MicroBitPin *ioP4() { return &uBit.io.P4; }
|
||||
MicroBitPin *ioP5() { return &uBit.io.P5; }
|
||||
MicroBitPin *ioP6() { return &uBit.io.P6; }
|
||||
MicroBitPin *ioP7() { return &uBit.io.P7; }
|
||||
MicroBitPin *ioP8() { return &uBit.io.P8; }
|
||||
MicroBitPin *ioP9() { return &uBit.io.P9; }
|
||||
MicroBitPin *ioP10() { return &uBit.io.P10; }
|
||||
MicroBitPin *ioP11() { return &uBit.io.P11; }
|
||||
MicroBitPin *ioP12() { return &uBit.io.P12; }
|
||||
MicroBitPin *ioP13() { return &uBit.io.P13; }
|
||||
MicroBitPin *ioP14() { return &uBit.io.P14; }
|
||||
MicroBitPin *ioP15() { return &uBit.io.P15; }
|
||||
MicroBitPin *ioP16() { return &uBit.io.P16; }
|
||||
MicroBitPin *ioP19() { return &uBit.io.P19; }
|
||||
MicroBitPin *ioP20() { return &uBit.io.P20; }
|
||||
|
||||
void panic(int code)
|
||||
{
|
||||
uBit.panic(code);
|
||||
}
|
||||
|
||||
void serialSendString(StringData *s)
|
||||
{
|
||||
uBit.serial.sendString(ManagedString(s));
|
||||
}
|
||||
|
||||
StringData *serialReadString()
|
||||
{
|
||||
return uBit.serial.readString().leakData();
|
||||
}
|
||||
|
||||
void serialSendImage(ImageData *img)
|
||||
{
|
||||
uBit.serial.sendImage(MicroBitImage(img));
|
||||
}
|
||||
|
||||
ImageData *serialReadImage(int width, int height)
|
||||
{
|
||||
return uBit.serial.readImage(width, height).leakData();
|
||||
}
|
||||
|
||||
void serialSendDisplayState() { uBit.serial.sendDisplayState(); }
|
||||
void serialReadDisplayState() { uBit.serial.readDisplayState(); }
|
||||
|
||||
void i2cReadBuffer(int address, RefBuffer *buf)
|
||||
{
|
||||
uBit.i2c.read(address << 1, buffer::cptr(buf), buffer::count(buf));
|
||||
}
|
||||
|
||||
void i2cWriteBuffer(int address, RefBuffer *buf)
|
||||
{
|
||||
uBit.i2c.write(address << 1, buffer::cptr(buf), buffer::count(buf));
|
||||
}
|
||||
|
||||
int i2cReadRaw(int address, char *data, int length, int repeated)
|
||||
{
|
||||
return uBit.i2c.read(address, data, length, repeated);
|
||||
}
|
||||
|
||||
int i2cWriteRaw(int address, const char *data, int length, int repeated)
|
||||
{
|
||||
return uBit.i2c.write(address, data, length, repeated);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void error(ERROR code, int subcode)
|
||||
{
|
||||
printf("Error: %d [%d]\n", code, subcode);
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
uint32_t *globals;
|
||||
int numGlobals;
|
||||
|
||||
uint32_t *allocate(uint16_t sz)
|
||||
{
|
||||
uint32_t *arr = new uint32_t[sz];
|
||||
memset(arr, 0, sz * 4);
|
||||
return arr;
|
||||
}
|
||||
|
||||
void checkStr(bool cond, const char *msg)
|
||||
{
|
||||
if (!cond) {
|
||||
while (true) {
|
||||
micro_bit::scrollString(msg, 100);
|
||||
micro_bit::pause(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int templateHash()
|
||||
{
|
||||
return ((int*)bytecode)[4];
|
||||
}
|
||||
|
||||
int programHash()
|
||||
{
|
||||
return ((int*)bytecode)[6];
|
||||
}
|
||||
|
||||
void exec_binary(uint16_t *pc)
|
||||
{
|
||||
// XXX re-enable once the calibration code is fixed and [editor/embedded.ts]
|
||||
// properly prepends a call to [internal_main].
|
||||
// ::touch_develop::internal_main();
|
||||
|
||||
// unique group for radio based on source hash
|
||||
::touch_develop::micro_bit::radioDefaultGroup = programHash();
|
||||
|
||||
// repeat error 4 times and restart as needed
|
||||
uBit.display.setErrorTimeout(4);
|
||||
|
||||
uint32_t ver = *pc++;
|
||||
checkStr(ver == 0x4207, ":( Bad runtime version");
|
||||
numGlobals = *pc++;
|
||||
globals = allocate(numGlobals);
|
||||
|
||||
bytecode = *((uint16_t**)pc); // the actual bytecode is here
|
||||
pc += 2;
|
||||
|
||||
// just compare the first word
|
||||
checkStr(((uint32_t*)bytecode)[0] == 0x923B8E70 &&
|
||||
templateHash() == ((int*)pc)[0],
|
||||
":( Failed partial flash");
|
||||
|
||||
uint32_t startptr = (uint32_t)bytecode;
|
||||
startptr += 48; // header
|
||||
startptr |= 1; // Thumb state
|
||||
|
||||
((uint32_t (*)())startptr)();
|
||||
|
||||
#ifdef DEBUG_MEMLEAKS
|
||||
bitvm::debugMemLeaks();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
exec_binary((uint16_t*)functionsAndBytecode);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace bitvm;
|
||||
|
||||
#include "ext/refs.inc"
|
||||
|
||||
namespace bitvm {
|
||||
// The ARM Thumb generator in the JavaScript code is parsing
|
||||
// the hex file and looks for the magic numbers as present here.
|
||||
//
|
||||
// Then it fetches function pointer addresses from there.
|
||||
//
|
||||
// The code generator will assert if the Touch Develop function
|
||||
// has different number of input/output parameters than the one
|
||||
// defined here.
|
||||
//
|
||||
// It of course should match the C++ implementation.
|
||||
|
||||
const uint32_t functionsAndBytecode[] __attribute__((aligned(0x20))) = {
|
||||
// Magic header to find it in the file
|
||||
0x08010801, 0x42424242, 0x08010801, 0x8de9d83e,
|
||||
// List of pointers generated by scripts/functionTable.js
|
||||
#include "generated/pointers.inc"
|
||||
// Pointers from extensions
|
||||
#include "ext/pointers.inc"
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
// vim: ts=2 sw=2 expandtab
|
|
@ -0,0 +1,336 @@
|
|||
#include "kindscript.h"
|
||||
|
||||
/*
|
||||
#include <cstdlib>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace ks {
|
||||
int incr(uint32_t e)
|
||||
{
|
||||
if (e) {
|
||||
if (hasVTable(e))
|
||||
((RefObject*)e)->ref();
|
||||
else
|
||||
((RefCounted*)e)->incr();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
void decr(uint32_t e)
|
||||
{
|
||||
if (e) {
|
||||
if (hasVTable(e))
|
||||
((RefObject*)e)->unref();
|
||||
else
|
||||
((RefCounted*)e)->decr();
|
||||
}
|
||||
}
|
||||
|
||||
Action mkAction(int reflen, int totallen, int startptr)
|
||||
{
|
||||
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
|
||||
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
|
||||
check(bytecode[startptr] == 0xffff, ERR_INVALID_BINARY_HEADER, 3);
|
||||
check(bytecode[startptr + 1] == 0, ERR_INVALID_BINARY_HEADER, 4);
|
||||
|
||||
|
||||
uint32_t tmp = (uint32_t)&bytecode[startptr];
|
||||
|
||||
if (totallen == 0) {
|
||||
return tmp; // no closure needed
|
||||
}
|
||||
|
||||
void *ptr = ::operator new(sizeof(RefAction) + totallen * sizeof(uint32_t));
|
||||
RefAction *r = new (ptr) RefAction();
|
||||
r->len = totallen;
|
||||
r->reflen = reflen;
|
||||
r->func = (ActionCB)((tmp + 4) | 1);
|
||||
memset(r->fields, 0, r->len * sizeof(uint32_t));
|
||||
|
||||
return (Action)r;
|
||||
}
|
||||
|
||||
void runAction1(Action a, int arg)
|
||||
{
|
||||
if (hasVTable(a))
|
||||
((RefAction*)a)->runCore(arg);
|
||||
else {
|
||||
check(*(uint16_t*)a == 0xffff, ERR_INVALID_BINARY_HEADER, 4);
|
||||
((ActionCB)((a + 4) | 1))(NULL, NULL, arg);
|
||||
}
|
||||
}
|
||||
|
||||
void runAction0(Action a)
|
||||
{
|
||||
runAction1(a, 0);
|
||||
}
|
||||
|
||||
RefRecord* mkRecord(int reflen, int totallen)
|
||||
{
|
||||
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
|
||||
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
|
||||
|
||||
void *ptr = ::operator new(sizeof(RefRecord) + totallen * sizeof(uint32_t));
|
||||
RefRecord *r = new (ptr) RefRecord();
|
||||
r->len = totallen;
|
||||
r->reflen = reflen;
|
||||
memset(r->fields, 0, r->len * sizeof(uint32_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t RefRecord::ld(int idx)
|
||||
{
|
||||
check(reflen <= idx && idx < len, ERR_OUT_OF_BOUNDS, 1);
|
||||
return fields[idx];
|
||||
}
|
||||
|
||||
uint32_t RefRecord::ldref(int idx)
|
||||
{
|
||||
//printf("LD %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
|
||||
check(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 2);
|
||||
uint32_t tmp = fields[idx];
|
||||
incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void RefRecord::st(int idx, uint32_t v)
|
||||
{
|
||||
check(reflen <= idx && idx < len, ERR_OUT_OF_BOUNDS, 3);
|
||||
fields[idx] = v;
|
||||
}
|
||||
|
||||
void RefRecord::stref(int idx, uint32_t v)
|
||||
{
|
||||
//printf("ST %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
|
||||
check(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 4);
|
||||
decr(fields[idx]);
|
||||
fields[idx] = v;
|
||||
}
|
||||
|
||||
RefRecord::~RefRecord()
|
||||
{
|
||||
//printf("DELREC: %p\n", this);
|
||||
for (int i = 0; i < this->reflen; ++i) {
|
||||
decr(fields[i]);
|
||||
fields[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RefRecord::print()
|
||||
{
|
||||
printf("RefRecord %p r=%d size=%d (%d refs)\n", this, refcnt, len, reflen);
|
||||
}
|
||||
|
||||
|
||||
void RefCollection::push(uint32_t x) {
|
||||
if (flags & 1) incr(x);
|
||||
data.push_back(x);
|
||||
}
|
||||
|
||||
uint32_t RefCollection::getAt(int x) {
|
||||
if (in_range(x)) {
|
||||
uint32_t tmp = data.at(x);
|
||||
if (flags & 1) incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
else {
|
||||
error(ERR_OUT_OF_BOUNDS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RefCollection::removeAt(int x) {
|
||||
if (!in_range(x))
|
||||
return;
|
||||
|
||||
if (flags & 1) decr(data.at(x));
|
||||
data.erase(data.begin()+x);
|
||||
}
|
||||
|
||||
void RefCollection::setAt(int x, uint32_t y) {
|
||||
if (!in_range(x))
|
||||
return;
|
||||
|
||||
if (flags & 1) {
|
||||
decr(data.at(x));
|
||||
incr(y);
|
||||
}
|
||||
data.at(x) = y;
|
||||
}
|
||||
|
||||
int RefCollection::indexOf(uint32_t x, int start) {
|
||||
if (!in_range(start))
|
||||
return -1;
|
||||
|
||||
if (flags & 2) {
|
||||
StringData *xx = (StringData*)x;
|
||||
for (uint32_t i = start; i < data.size(); ++i) {
|
||||
StringData *ee = (StringData*)data.at(i);
|
||||
if (xx->len == ee->len && memcmp(xx->data, ee->data, xx->len) == 0)
|
||||
return (int)i;
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = start; i < data.size(); ++i)
|
||||
if (data.at(i) == x)
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int RefCollection::removeElement(uint32_t x) {
|
||||
int idx = indexOf(x, 0);
|
||||
if (idx >= 0) {
|
||||
removeAt(idx);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEMLEAKS
|
||||
std::set<RefObject*> allptrs;
|
||||
void debugMemLeaks()
|
||||
{
|
||||
printf("LIVE POINTERS:\n");
|
||||
for(std::set<RefObject*>::iterator itr = allptrs.begin();itr!=allptrs.end();itr++)
|
||||
{
|
||||
(*itr)->print();
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
void debugMemLeaks() {}
|
||||
#endif
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// An adapter for the API expected by the run-time.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
map<pair<int, int>, Action> handlersMap;
|
||||
|
||||
// We have the invariant that if [dispatchEvent] is registered against the DAL
|
||||
// for a given event, then [handlersMap] contains a valid entry for that
|
||||
// event.
|
||||
void dispatchEvent(MicroBitEvent e) {
|
||||
Action curr = handlersMap[{ e.source, e.value }];
|
||||
if (curr)
|
||||
runAction1(curr, e.value);
|
||||
|
||||
curr = handlersMap[{ e.source, MICROBIT_EVT_ANY }];
|
||||
if (curr)
|
||||
runAction1(curr, e.value);
|
||||
}
|
||||
|
||||
void registerWithDal(int id, int event, Action a) {
|
||||
Action prev = handlersMap[{ id, event }];
|
||||
if (prev)
|
||||
decr(prev);
|
||||
else
|
||||
uBit.MessageBus.listen(id, event, dispatchEvent);
|
||||
incr(a);
|
||||
handlersMap[{ id, event }] = a;
|
||||
}
|
||||
|
||||
void fiberDone(void *a)
|
||||
{
|
||||
decr((Action)a);
|
||||
release_fiber();
|
||||
}
|
||||
|
||||
|
||||
void runInBackground(Action a) {
|
||||
if (a != 0) {
|
||||
incr(a);
|
||||
create_fiber((void(*)(void*))runAction0, (void*)a, fiberDone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void error(ERROR code, int subcode)
|
||||
{
|
||||
printf("Error: %d [%d]\n", code, subcode);
|
||||
panic(42);
|
||||
}
|
||||
|
||||
|
||||
uint32_t *globals;
|
||||
int numGlobals;
|
||||
|
||||
uint32_t *allocate(uint16_t sz)
|
||||
{
|
||||
uint32_t *arr = new uint32_t[sz];
|
||||
memset(arr, 0, sz * 4);
|
||||
return arr;
|
||||
}
|
||||
|
||||
void checkStr(bool cond, const char *msg)
|
||||
{
|
||||
if (!cond) {
|
||||
while (true) {
|
||||
uBit.display.scroll(msg, 100);
|
||||
uBit.sleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int templateHash()
|
||||
{
|
||||
return ((int*)bytecode)[4];
|
||||
}
|
||||
|
||||
int programHash()
|
||||
{
|
||||
return ((int*)bytecode)[6];
|
||||
}
|
||||
|
||||
void exec_binary(uint16_t *pc)
|
||||
{
|
||||
// XXX re-enable once the calibration code is fixed and [editor/embedded.ts]
|
||||
// properly prepends a call to [internal_main].
|
||||
// ::touch_develop::internal_main();
|
||||
|
||||
// unique group for radio based on source hash
|
||||
// ::touch_develop::micro_bit::radioDefaultGroup = programHash();
|
||||
|
||||
// repeat error 4 times and restart as needed
|
||||
uBit.display.setErrorTimeout(4);
|
||||
|
||||
uint32_t ver = *pc++;
|
||||
checkStr(ver == 0x4208, ":( Bad runtime version");
|
||||
numGlobals = *pc++;
|
||||
globals = allocate(numGlobals);
|
||||
|
||||
bytecode = *((uint16_t**)pc); // the actual bytecode is here
|
||||
pc += 2;
|
||||
|
||||
// just compare the first word
|
||||
checkStr(((uint32_t*)bytecode)[0] == 0x923B8E70 &&
|
||||
templateHash() == ((int*)pc)[0],
|
||||
":( Failed partial flash");
|
||||
|
||||
uint32_t startptr = (uint32_t)bytecode;
|
||||
startptr += 48; // header
|
||||
startptr |= 1; // Thumb state
|
||||
|
||||
((uint32_t (*)())startptr)();
|
||||
|
||||
#ifdef DEBUG_MEMLEAKS
|
||||
bitvm::debugMemLeaks();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
exec_binary((uint16_t*)functionsAndBytecode);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: ts=2 sw=2 expandtab
|
Загрузка…
Ссылка в новой задаче