From a467c2de772120ac05187027f73a41f1d72d488a Mon Sep 17 00:00:00 2001 From: Tom Ball Date: Tue, 7 Jan 2025 14:19:28 -0800 Subject: [PATCH] Remove arcade shield (#6054) * remove arcadeshield from libs and rename * add back until tested new one * add robot tutorial * add robot tutorials * remove gallery stuff * remove arcadeshield doc * remove archived one * bump * redo --- .../_locales/arcadeshield-jsdoc-strings.json | 26 -- .../_locales/arcadeshield-strings.json | 6 - libs/arcadeshield/arcadegamepad.h | 49 --- libs/arcadeshield/arcadesound.h | 31 -- libs/arcadeshield/config_nrf.h | 69 ---- libs/arcadeshield/controllerbuttons.cpp | 168 -------- libs/arcadeshield/indexedscreen.h | 85 ----- libs/arcadeshield/jddisplay.cpp | 359 ------------------ libs/arcadeshield/jddisplay.h | 67 ---- libs/arcadeshield/jdprotocol.h | 125 ------ libs/arcadeshield/pins.cpp | 71 ---- libs/arcadeshield/pinsDigital.cpp | 142 ------- libs/arcadeshield/pxt.json | 39 -- libs/arcadeshield/screen.cpp | 348 ----------------- libs/arcadeshield/screenhelpers.d.ts | 14 - libs/arcadeshield/shims.d.ts | 159 -------- libs/arcadeshield/test.ts | 29 -- pxtarget.json | 1 - targetconfig.json | 2 +- 19 files changed, 1 insertion(+), 1789 deletions(-) delete mode 100644 libs/arcadeshield/_locales/arcadeshield-jsdoc-strings.json delete mode 100644 libs/arcadeshield/_locales/arcadeshield-strings.json delete mode 100644 libs/arcadeshield/arcadegamepad.h delete mode 100644 libs/arcadeshield/arcadesound.h delete mode 100644 libs/arcadeshield/config_nrf.h delete mode 100644 libs/arcadeshield/controllerbuttons.cpp delete mode 100644 libs/arcadeshield/indexedscreen.h delete mode 100644 libs/arcadeshield/jddisplay.cpp delete mode 100644 libs/arcadeshield/jddisplay.h delete mode 100644 libs/arcadeshield/jdprotocol.h delete mode 100644 libs/arcadeshield/pins.cpp delete mode 100644 libs/arcadeshield/pinsDigital.cpp delete mode 100644 libs/arcadeshield/pxt.json delete mode 100644 libs/arcadeshield/screen.cpp delete mode 100644 libs/arcadeshield/screenhelpers.d.ts delete mode 100644 libs/arcadeshield/shims.d.ts delete mode 100644 libs/arcadeshield/test.ts diff --git a/libs/arcadeshield/_locales/arcadeshield-jsdoc-strings.json b/libs/arcadeshield/_locales/arcadeshield-jsdoc-strings.json deleted file mode 100644 index d72021bb5a6..00000000000 --- a/libs/arcadeshield/_locales/arcadeshield-jsdoc-strings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "Bitmap.clone": "Return a copy of the current bitmap", - "Bitmap.copyFrom": "Sets all pixels in the current bitmap from the other bitmap, which has to be of the same size and\nbpp.", - "Bitmap.doubled": "Stretches the bitmap in both directions by 100%", - "Bitmap.doubledX": "Stretches the bitmap horizontally by 100%", - "Bitmap.doubledY": "Stretches the bitmap vertically by 100%", - "Bitmap.drawBitmap": "Draw given bitmap on the current bitmap", - "Bitmap.drawTransparentBitmap": "Draw given bitmap with transparent background on the current bitmap", - "Bitmap.fill": "Fill entire bitmap with a given color", - "Bitmap.flipX": "Flips (mirrors) pixels horizontally in the current bitmap", - "Bitmap.flipY": "Flips (mirrors) pixels vertically in the current bitmap", - "Bitmap.getPixel": "Get a pixel color", - "Bitmap.getRows": "Copy row(s) of pixel from bitmap to buffer (8 bit per pixel).", - "Bitmap.height": "Get the height of the bitmap", - "Bitmap.isMono": "True if the bitmap is monochromatic (black and white)", - "Bitmap.overlapsWith": "Check if the current bitmap \"collides\" with another", - "Bitmap.replace": "Replaces one color in an bitmap with another", - "Bitmap.scroll": "Every pixel in bitmap is moved by (dx,dy)", - "Bitmap.setPixel": "Set pixel color", - "Bitmap.setRows": "Copy row(s) of pixel from buffer to bitmap.", - "Bitmap.transposed": "Returns a transposed bitmap (with X/Y swapped)", - "Bitmap.width": "Get the width of the bitmap", - "bitmaps.create": "Create new empty (transparent) bitmap", - "bitmaps.doubledIcon": "Double the size of an icon", - "bitmaps.ofBuffer": "Create new bitmap with given content" -} \ No newline at end of file diff --git a/libs/arcadeshield/_locales/arcadeshield-strings.json b/libs/arcadeshield/_locales/arcadeshield-strings.json deleted file mode 100644 index e56310a6517..00000000000 --- a/libs/arcadeshield/_locales/arcadeshield-strings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "bitmaps|block": "bitmaps", - "{id:category}Bitmap": "Bitmap", - "{id:category}Bitmaps": "Bitmaps", - "{id:category}__screenhelpers": "__screenhelpers" -} \ No newline at end of file diff --git a/libs/arcadeshield/arcadegamepad.h b/libs/arcadeshield/arcadegamepad.h deleted file mode 100644 index bcfe4577511..00000000000 --- a/libs/arcadeshield/arcadegamepad.h +++ /dev/null @@ -1,49 +0,0 @@ -// Autogenerated C header file for Arcade Gamepad -#ifndef _JACDAC_SPEC_ARCADE_GAMEPAD_H -#define _JACDAC_SPEC_ARCADE_GAMEPAD_H 1 - -#define JD_SERVICE_CLASS_ARCADE_GAMEPAD 0x1deaa06e - -// enum Button (uint8_t) -#define JD_ARCADE_GAMEPAD_BUTTON_LEFT 0x1 -#define JD_ARCADE_GAMEPAD_BUTTON_UP 0x2 -#define JD_ARCADE_GAMEPAD_BUTTON_RIGHT 0x3 -#define JD_ARCADE_GAMEPAD_BUTTON_DOWN 0x4 -#define JD_ARCADE_GAMEPAD_BUTTON_A 0x5 -#define JD_ARCADE_GAMEPAD_BUTTON_B 0x6 -#define JD_ARCADE_GAMEPAD_BUTTON_MENU 0x7 -#define JD_ARCADE_GAMEPAD_BUTTON_SELECT 0x8 -#define JD_ARCADE_GAMEPAD_BUTTON_RESET 0x9 -#define JD_ARCADE_GAMEPAD_BUTTON_EXIT 0xa - -/** - * Indicates which buttons are currently active (pressed). - * `pressure` should be `0xff` for digital buttons, and proportional for analog ones. - */ -#define JD_ARCADE_GAMEPAD_REG_BUTTONS JD_REG_READING -typedef struct jd_arcade_gamepad_buttons { - uint8_t button; // Button - uint8_t pressure; // ratio u0.8 -} jd_arcade_gamepad_buttons_t; - - -/** - * Constant. Indicates number of players supported and which buttons are present on the controller. - */ -#define JD_ARCADE_GAMEPAD_REG_AVAILABLE_BUTTONS 0x180 -typedef struct jd_arcade_gamepad_available_buttons { - uint8_t button[0]; // Button -} jd_arcade_gamepad_available_buttons_t; - - -/** - * Argument: button Button (uint8_t). Emitted when button goes from inactive to active. - */ -#define JD_ARCADE_GAMEPAD_EV_DOWN JD_EV_ACTIVE - -/** - * Argument: button Button (uint8_t). Emitted when button goes from active to inactive. - */ -#define JD_ARCADE_GAMEPAD_EV_UP JD_EV_INACTIVE - -#endif diff --git a/libs/arcadeshield/arcadesound.h b/libs/arcadeshield/arcadesound.h deleted file mode 100644 index 7b47d360c9d..00000000000 --- a/libs/arcadeshield/arcadesound.h +++ /dev/null @@ -1,31 +0,0 @@ -// Autogenerated C header file for Arcade sound -#ifndef _JACDAC_SPEC_ARCADE_SOUND_H -#define _JACDAC_SPEC_ARCADE_SOUND_H 1 - -#define JD_SERVICE_CLASS_ARCADE_SOUND 0x1fc63606 - -/** - * Argument: samples bytes. Play samples, which are single channel, signed 16-bit little endian values. - */ -#define JD_ARCADE_SOUND_CMD_PLAY 0x80 - -/** - * Read-write Hz u22.10 (uint32_t). Get or set playback sample rate (in samples per second). - * If you set it, read it back, as the value may be rounded up or down. - */ -#define JD_ARCADE_SOUND_REG_SAMPLE_RATE 0x80 - -/** - * Constant B uint32_t. The size of the internal audio buffer. - */ -#define JD_ARCADE_SOUND_REG_BUFFER_SIZE 0x180 - -/** - * Read-only B uint32_t. How much data is still left in the buffer to play. - * Clients should not send more data than `buffer_size - buffer_pending`, - * but can keep the `buffer_pending` as low as they want to ensure low latency - * of audio playback. - */ -#define JD_ARCADE_SOUND_REG_BUFFER_PENDING 0x181 - -#endif diff --git a/libs/arcadeshield/config_nrf.h b/libs/arcadeshield/config_nrf.h deleted file mode 100644 index 8c8a531e48f..00000000000 --- a/libs/arcadeshield/config_nrf.h +++ /dev/null @@ -1,69 +0,0 @@ -// here we hard code the dependence on micro:bit V2 -// and Arcade Shield, to avoid potential conflicts with pxt-microbit - -#include "NRF52Pin.h" -#include "NRF52SPI.h" - -#define CODAL_PIN NRF52Pin -#define CODAL_SPI NRF52SPI - -#define MY_DISPLAY_TYPE 4242 // smart shield -#define MY_DISPLAY_CFG0 0x02000080 // allow execution without shield plugged in -#define MY_DISPLAY_CFG1 0x00000603 -#define MY_DISPLAY_CFG2 8 // maximum SPI frequency for smart shield - -#define MY_PIN_BTNMX_LATCH &uBit.io.P9 // DAL.P0_9 -#define MY_PIN_BTNMX_CLOCK &uBit.io.P20 // DAL.P1_0 -#define MY_PIN_BTNMX_DATA &uBit.io.P14 // DAL.P0_1 - -#define MY_PIN_DISPLAY_SCK &uBit.io.P13 // DAL.P0_17 -#define MY_PIN_DISPLAY_MOSI &uBit.io.P15 // DAL.P0_13 -#define MY_PIN_DISPLAY_MISO &uBit.io.P14 // DAL.P0_1 -#define MY_PIN_DISPLAY_BL &uBit.io.P19 // DAL.P0_26 -#define MY_PIN_DISPLAY_DC &uBit.io.P8 // DAL.P0_10 -#define MY_PIN_DISPLAY_RST &uBit.io.P16 // DAL.P1_2 -#define MY_PIN_DISPLAY_CS ((CODAL_PIN*)NULL) // not connected -#define MY_PIN_LED ((CODAL_PIN*)NULL) // not connected - -#undef DEV_NUM_PINS -#define DEV_NUM_PINS 48 -#define DEVICE_ID_IO_P0 100 - -#define DEV_PWM_PINS 0x0000ffffffffULL // all pins are PWM pins it seems -#define DEV_AIN_PINS 0x0000f000001fULL - -// Codal doesn't yet distinguish between PWM and AIN -#define DEV_ANALOG_PINS (DEV_PWM_PINS | DEV_AIN_PINS) - -#ifndef IS_ANALOG_PIN -#define IS_ANALOG_PIN(id) ((DEV_ANALOG_PINS >> (id)) & 1) -#endif - -typedef CODAL_PIN DevicePin; - -typedef DevicePin *DigitalInOutPin; -typedef DevicePin *AnalogInOutPin; -typedef DevicePin *AnalogInPin; -typedef DevicePin *AnalogOutPin; -typedef DevicePin *PwmPin; -typedef DevicePin *PwmOnlyPin; - -// remove the indirection through configuration -#undef PIN -#undef LOOKUP_PIN -#define PIN(name) MY_PIN_##name -#define LOOKUP_PIN(name) PIN(name) // pxt::myLookupPin(PIN(name)) - -#define PXT_INTERNAL_KEY_UP 2050 -#define PXT_INTERNAL_KEY_DOWN 2051 -#define DEVICE_ID_FIRST_BUTTON 4000 -#define BUTTON_ACTIVE_LOW_PULL_UP 32 - -namespace pxt { - uint32_t readButtonMultiplexer(int bits); - void disableButtonMultiplexer(); - DevicePin *myLookupPin(int pinName); - CodalComponent *lookupComponent(int id); - int pressureLevelByButtonId(int btnId, int codalId); -} - diff --git a/libs/arcadeshield/controllerbuttons.cpp b/libs/arcadeshield/controllerbuttons.cpp deleted file mode 100644 index bea8b4eef19..00000000000 --- a/libs/arcadeshield/controllerbuttons.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "pxt.h" - -#undef Button - -#include "Pin.h" -#define PinCompat codal::Pin - -#include "config_nrf.h" - -namespace pxt { - - -class PressureButton : public codal::Button { - public: - PressureButton(Pin &pin, uint16_t id, - ButtonEventConfiguration eventConfiguration = DEVICE_BUTTON_ALL_EVENTS, - ButtonPolarity polarity = ACTIVE_LOW, PullMode mode = PullMode::None) - : Button(pin, id, eventConfiguration, polarity, mode) {} - - virtual int pressureLevel() { return isPressed() ? 512 : 0; } -}; - -struct AnalogCache { - AnalogCache *next; - Pin *pin; - uint32_t lastMeasureMS; - uint16_t lastMeasure; - AnalogCache(Pin *pin) : pin(pin) { - next = NULL; - lastMeasureMS = 0; - lastMeasure = pin->getAnalogValue(); - } - uint16_t read(); -}; - -uint16_t AnalogCache::read() { - uint32_t now = current_time_ms(); - if (now - lastMeasureMS < 50) - return lastMeasure; - lastMeasureMS = now; - lastMeasure = pin->getAnalogValue(); - return lastMeasure; -} - -static AnalogCache *analogCache; - -class AnalogButton : public PressureButton { - public: - AnalogCache *cache; - int16_t threshold; - bool state; - - AnalogButton(AnalogCache *cache, uint16_t id, int threshold) - : PressureButton(*cache->pin, id), cache(cache), threshold(threshold), state(false) {} - - protected: - virtual int pressureLevel() override { - int v = cache->read() - 512; - if (threshold < 0) - v = -v; - int vmin = getConfig(CFG_ANALOG_JOYSTICK_MIN, 50); - int vmax = getConfig(CFG_ANALOG_JOYSTICK_MAX, 500); - v = (v - vmin) * 512 / (vmax - vmin); - if (v < 0) - v = 0; - if (v > 512) - v = 512; - return v; - } - - virtual int buttonActive() override { - int v = cache->read() - 512; - int thr = threshold; - - if (thr < 0) { - v = -v; - thr = -thr; - } - - if (v > thr) - state = true; - else if (state && v > thr * 3 / 4) - state = true; - else - state = false; - - return state; - } -}; - -AnalogCache *lookupAnalogCache(Pin *pin) { - for (auto c = analogCache; c; c = c->next) - if (c->pin == pin) - return c; - auto c = new AnalogCache(pin); - c->next = analogCache; - analogCache = c; - return c; -} - -int multiplexedButtonIsPressed(int btnId); -int registerMultiplexedButton(int pin, int buttonId); - -//% expose -int pressureLevelByButtonId(int btnId, int codalId) { - if (codalId <= 0) - codalId = DEVICE_ID_FIRST_BUTTON + btnId; - auto btn = (PressureButton *)lookupComponent(codalId); - if (!btn) { - return multiplexedButtonIsPressed(btnId) ? 512 : 0; - } - return btn->pressureLevel(); -} - -static void sendBtnDown(Event ev) { - Event(PXT_INTERNAL_KEY_DOWN, ev.source - DEVICE_ID_FIRST_BUTTON); -} - -static void sendBtnUp(Event ev) { - Event(PXT_INTERNAL_KEY_UP, ev.source - DEVICE_ID_FIRST_BUTTON); -} - -//% expose -void setupButton(int buttonId, int key) { - int pin = getConfig(key); - if (pin == -1) - return; - - unsigned highflags = (unsigned)pin >> 16; - int flags = BUTTON_ACTIVE_LOW_PULL_UP; - if (highflags & 0xff) - flags = highflags & 0xff; - - pin &= 0xffff; - - auto cpid = DEVICE_ID_FIRST_BUTTON + buttonId; - auto btn = (PressureButton *)lookupComponent(cpid); - if (btn == NULL) { - if (registerMultiplexedButton(pin, buttonId)) - return; - - if (1100 <= pin && pin < 1300) { - pin -= 1100; - int thr = getConfig(CFG_ANALOG_BUTTON_THRESHOLD, 300); - if (pin >= 100) { - thr = -thr; - pin -= 100; - } - btn = new AnalogButton(lookupAnalogCache(myLookupPin(pin)), cpid, thr); - } else { - auto pull = PullMode::None; - if ((flags & 0xf0) == 0x10) - pull = PullMode::Down; - else if ((flags & 0xf0) == 0x20) - pull = PullMode::Up; - else if ((flags & 0xf0) == 0x30) - pull = PullMode::None; - else - oops(3); - btn = new PressureButton(*myLookupPin(pin), cpid, DEVICE_BUTTON_ALL_EVENTS, - (ButtonPolarity)(flags & 0xf), pull); - } - EventModel::defaultEventBus->listen(btn->id, DEVICE_BUTTON_EVT_DOWN, sendBtnDown); - EventModel::defaultEventBus->listen(btn->id, DEVICE_BUTTON_EVT_UP, sendBtnUp); - } -} - -} // namespace pxt diff --git a/libs/arcadeshield/indexedscreen.h b/libs/arcadeshield/indexedscreen.h deleted file mode 100644 index 1cc0005a4b2..00000000000 --- a/libs/arcadeshield/indexedscreen.h +++ /dev/null @@ -1,85 +0,0 @@ -// Autogenerated C header file for Indexed screen -#ifndef _JACDAC_SPEC_INDEXED_SCREEN_H -#define _JACDAC_SPEC_INDEXED_SCREEN_H 1 - -#define JD_SERVICE_CLASS_INDEXED_SCREEN 0x16fa36e5 - -/** - * Sets the update window for subsequent `set_pixels` commands. - */ -#define JD_INDEXED_SCREEN_CMD_START_UPDATE 0x81 -typedef struct jd_indexed_screen_start_update { - uint16_t x; // px - uint16_t y; // px - uint16_t width; // px - uint16_t height; // px -} jd_indexed_screen_start_update_t; - - -/** - * Argument: pixels bytes. Set pixels in current window, according to current palette. - * Each "line" of data is aligned to a byte. - */ -#define JD_INDEXED_SCREEN_CMD_SET_PIXELS 0x83 - -/** - * Read-write ratio u0.8 (uint8_t). Set backlight brightness. - * If set to `0` the display may go to sleep. - */ -#define JD_INDEXED_SCREEN_REG_BRIGHTNESS JD_REG_INTENSITY - -/** - * The current palette. - * The color entry repeats `1 << bits_per_pixel` times. - * This register may be write-only. - */ -#define JD_INDEXED_SCREEN_REG_PALETTE 0x80 -typedef struct jd_indexed_screen_palette { - uint8_t blue; - uint8_t green; - uint8_t red; - uint8_t padding; -} jd_indexed_screen_palette_t; - - -/** - * Constant bit uint8_t. Determines the number of palette entries. - * Typical values are 1, 2, 4, or 8. - */ -#define JD_INDEXED_SCREEN_REG_BITS_PER_PIXEL 0x180 - -/** - * Constant px uint16_t. Screen width in "natural" orientation. - */ -#define JD_INDEXED_SCREEN_REG_WIDTH 0x181 - -/** - * Constant px uint16_t. Screen height in "natural" orientation. - */ -#define JD_INDEXED_SCREEN_REG_HEIGHT 0x182 - -/** - * Read-write bool (uint8_t). If true, consecutive pixels in the "width" direction are sent next to each other (this is typical for graphics cards). - * If false, consecutive pixels in the "height" direction are sent next to each other. - * For embedded screen controllers, this is typically true iff `width < height` - * (in other words, it's only true for portrait orientation screens). - * Some controllers may allow the user to change this (though the refresh order may not be optimal then). - * This is independent of the `rotation` register. - */ -#define JD_INDEXED_SCREEN_REG_WIDTH_MAJOR 0x81 - -/** - * Read-write px uint8_t. Every pixel sent over wire is represented by `up_sampling x up_sampling` square of physical pixels. - * Some displays may allow changing this (which will also result in changes to `width` and `height`). - * Typical values are 1 and 2. - */ -#define JD_INDEXED_SCREEN_REG_UP_SAMPLING 0x82 - -/** - * Read-write ° uint16_t. Possible values are 0, 90, 180 and 270 only. - * Write to this register do not affect `width` and `height` registers, - * and may be ignored by some screens. - */ -#define JD_INDEXED_SCREEN_REG_ROTATION 0x83 - -#endif diff --git a/libs/arcadeshield/jddisplay.cpp b/libs/arcadeshield/jddisplay.cpp deleted file mode 100644 index 4d444bbb834..00000000000 --- a/libs/arcadeshield/jddisplay.cpp +++ /dev/null @@ -1,359 +0,0 @@ -#include "pxt.h" - -#include "jddisplay.h" - -#include "config_nrf.h" - -#define VLOG NOLOG -//#define VLOG DMESG - -namespace pxt { - -codal::CodalDevice device; - -#define ALIGN(x) (((x) + 3) & ~3) - -static void jd_panic(void) { - target_panic(121); // PANIC_SCREEN_ERROR -} - -static int jd_shift_frame(jd_frame_t *frame) { - int psize = frame->size; - jd_packet_t *pkt = (jd_packet_t *)frame; - int oldsz = pkt->service_size + 4; - if (ALIGN(oldsz) >= psize) - return 0; // nothing to shift - - int ptr; - if (frame->data[oldsz] == 0xff) { - ptr = frame->data[oldsz + 1]; - if (ptr >= psize) - return 0; // End-of-frame - if (ptr <= oldsz) { - DMESG("invalid super-frame %d %d", ptr, oldsz); - return 0; // don't let it go back, must be some corruption - } - } else { - ptr = ALIGN(oldsz); - } - - // assume the first one got the ACK sorted - frame->flags &= ~JD_FRAME_FLAG_ACK_REQUESTED; - - uint8_t *src = &frame->data[ptr]; - int newsz = *src + 4; - if (ptr + newsz > psize) { - DMESG("invalid super-frame %d %d %d", ptr, newsz, psize); - return 0; - } - uint32_t *dst = (uint32_t *)frame->data; - uint32_t *srcw = (uint32_t *)src; - // don't trust memmove() - for (int i = 0; i < newsz; i += 4) - *dst++ = *srcw++; - // store ptr - ptr += ALIGN(newsz); - frame->data[newsz] = 0xff; - frame->data[newsz + 1] = ptr; - - return 1; -} - -static void *jd_push_in_frame(jd_frame_t *frame, unsigned service_num, unsigned service_cmd, - unsigned service_size) { - if (service_num >> 8) - jd_panic(); - if (service_cmd >> 16) - jd_panic(); - uint8_t *dst = frame->data + frame->size; - unsigned szLeft = (uint8_t *)frame + sizeof(*frame) - dst; - if (service_size + 4 > szLeft) - return NULL; - *dst++ = service_size; - *dst++ = service_num; - *dst++ = service_cmd & 0xff; - *dst++ = service_cmd >> 8; - frame->size += ALIGN(service_size + 4); - return dst; -} - -JDDisplay::JDDisplay(SPI *spi, Pin *cs, Pin *flow) : spi(spi), cs(cs), flow(flow) { - inProgress = false; - stepWaiting = false; - displayServiceNum = 0; - controlsStartServiceNum = 0; - controlsEndServiceNum = 0; - soundServiceNum = 0; - buttonState = 0; - brightness = 100; - soundBufferPending = 0; - soundSampleRate = 44100; - avgFrameTime = 26300; // start with a reasonable default - lastFrameTimestamp = 0; - - EventModel::defaultEventBus->listen(DEVICE_ID_DISPLAY, 4243, this, &JDDisplay::sendDone); - - flow->getDigitalValue(PullMode::Down); - EventModel::defaultEventBus->listen(flow->id, DEVICE_PIN_EVENT_ON_EDGE, this, - &JDDisplay::onFlowHi, MESSAGE_BUS_LISTENER_IMMEDIATE); - flow->eventOn(DEVICE_PIN_EVT_RISE); -} - -void JDDisplay::waitForSendDone() { - if (inProgress) - fiber_wait_for_event(DEVICE_ID_DISPLAY, 4242); -} - -void JDDisplay::sendDone(Event) { - inProgress = false; - Event(DEVICE_ID_DISPLAY, 4242); -} - -void *JDDisplay::queuePkt(uint32_t service_num, uint32_t service_cmd, uint32_t size) { - void *res = jd_push_in_frame(&sendFrame, service_num, service_cmd, size); - if (res == NULL) - target_panic(122); // PANIC_SCREEN_ERROR - return res; -} - -void JDDisplay::flushSend() { - if (cs) - cs->setDigitalValue(0); - spi->startTransfer((uint8_t *)&sendFrame, sizeof(sendFrame), (uint8_t *)&recvFrame, - sizeof(recvFrame), &JDDisplay::stepStatic, this); -} - -void JDDisplay::stepStatic(void *p) { - ((JDDisplay *)p)->step(); -} - -// We assume EIC IRQ pre-empts SPI/DMA IRQ (that is the numerical priority value of EIC is lower) -// This is true for codal STM32, SAMD, and NRF52 -void JDDisplay::onFlowHi(Event) { - if (stepWaiting) - step(); -} - -void JDDisplay::handleIncoming(jd_packet_t *pkt) { - if (pkt->service_number == JD_SERVICE_NUMBER_CTRL && - pkt->service_command == JD_CMD_ADVERTISEMENT_DATA) { - uint32_t *servptr = (uint32_t *)pkt->data; - int numServ = pkt->service_size >> 2; - for (uint8_t servIdx = 1; servIdx < numServ; ++servIdx) { - uint32_t service_class = servptr[servIdx]; - if (service_class == JD_SERVICE_CLASS_INDEXED_SCREEN) { - displayServiceNum = servIdx; - VLOG("JDA: found screen, serv=%d", servIdx); - } else if (service_class == JD_SERVICE_CLASS_ARCADE_GAMEPAD) { - if (!controlsStartServiceNum) - controlsStartServiceNum = servIdx; - controlsEndServiceNum = servIdx; - VLOG("JDA: found controls, serv=%d", servIdx); - } else if (service_class == JD_SERVICE_CLASS_ARCADE_SOUND) { - soundServiceNum = servIdx; - VLOG("JDA: found sound, serv=%d", servIdx); - } else { - VLOG("JDA: unknown service: %x", service_class); - } - } - } else if (pkt->service_number == JD_SERVICE_NUMBER_CTRL && - pkt->service_command == JD_CMD_CTRL_NOOP) { - // do nothing - } else if (pkt->service_number == soundServiceNum) { - switch (pkt->service_command) { - case JD_GET(JD_ARCADE_SOUND_REG_BUFFER_PENDING): - soundBufferPending = *(uint32_t *)pkt->data; - break; - case JD_GET(JD_ARCADE_SOUND_REG_SAMPLE_RATE): - soundSampleRate = *(uint32_t *)pkt->data >> 10; - break; - } - } else if (pkt->service_number == displayServiceNum) { - switch (pkt->service_command) { - case JD_GET(JD_INDEXED_SCREEN_REG_HEIGHT): - screenHeight = *(uint16_t *)pkt->data; - break; - case JD_GET(JD_INDEXED_SCREEN_REG_WIDTH): - screenWidth = *(uint16_t *)pkt->data; - break; - } - } else if (controlsStartServiceNum <= pkt->service_number && - pkt->service_number <= controlsEndServiceNum && - pkt->service_command == (JD_CMD_GET_REG | JD_REG_READING)) { - auto report = (jd_arcade_gamepad_buttons_t *)pkt->data; - auto endp = pkt->data + pkt->service_size; - uint32_t state = 0; - - while ((uint8_t *)report < endp) { - int idx = 0; - int b = report->button; - - if (report->pressure < 0x20) - continue; - - if (b == JD_ARCADE_GAMEPAD_BUTTON_SELECT) - b = JD_ARCADE_GAMEPAD_BUTTON_MENU; - - if (b == JD_ARCADE_GAMEPAD_BUTTON_RESET || b == JD_ARCADE_GAMEPAD_BUTTON_EXIT) - target_reset(); - - if (1 <= b && b <= 7) { - idx = b + 7 * (pkt->service_number - controlsStartServiceNum); - } - - if (idx > 0) - state |= 1 << idx; - - report++; - } - - if (state != buttonState) { - for (int i = 0; i < 32; ++i) { - if ((state & (1 << i)) && !(buttonState & (1 << i))) - Event(PXT_INTERNAL_KEY_DOWN, i); - if (!(state & (1 << i)) && (buttonState & (1 << i))) - Event(PXT_INTERNAL_KEY_UP, i); - } - buttonState = state; - } - } else { - // TODO remove later - VLOG("JDA: unknown packet for %d (cmd=%x)", pkt->service_number, pkt->service_command); - } -} - -void JDDisplay::step() { - if (cs) - cs->setDigitalValue(1); - - target_disable_irq(); - if (!flow->getDigitalValue()) { - stepWaiting = true; - target_enable_irq(); - return; - } else { - stepWaiting = false; - } - target_enable_irq(); - - memset(&sendFrame, 0, JD_SERIAL_FULL_HEADER_SIZE); - sendFrame.crc = JDSPI_MAGIC; - sendFrame.device_identifier = device.getSerialNumber(); - - if (recvFrame.crc == JDSPI_MAGIC_NOOP) { - // empty frame, skip - } else if (recvFrame.crc != JDSPI_MAGIC) { - DMESG("JDA: magic mismatch %x", (int)recvFrame.crc); - } else if (recvFrame.size == 0) { - // empty frame, skip - } else { - for (;;) { - handleIncoming((jd_packet_t *)&recvFrame); - if (!jd_shift_frame(&recvFrame)) - break; - } - } - - if (displayServiceNum == 0) { - // poke the control service to enumerate - queuePkt(JD_SERVICE_NUMBER_CTRL, JD_CMD_ADVERTISEMENT_DATA, 0); - flushSend(); - return; - } - - if (palette) { - { -#define PALETTE_SIZE (16 * 4) - auto cmd = - queuePkt(displayServiceNum, JD_SET(JD_INDEXED_SCREEN_REG_PALETTE), PALETTE_SIZE); - memcpy(cmd, palette, PALETTE_SIZE); - palette = NULL; - } - { - auto cmd = (jd_indexed_screen_start_update_t *)queuePkt( - displayServiceNum, JD_INDEXED_SCREEN_CMD_START_UPDATE, - sizeof(jd_indexed_screen_start_update_t)); - *cmd = this->addr; - } - { - auto cmd = - (uint8_t *)queuePkt(displayServiceNum, JD_SET(JD_INDEXED_SCREEN_REG_BRIGHTNESS), 1); - *cmd = this->brightness * 0xff / 100; - } - - if (soundServiceNum) { - // we only need this for sending sound - uint32_t now = (uint32_t)(pxt::current_time_ms()); - if (lastFrameTimestamp) { - uint32_t thisFrame = now - lastFrameTimestamp; - avgFrameTime = (avgFrameTime * 15 + thisFrame) >> 4; - } - lastFrameTimestamp = now; - // send around 2 frames of sound; typically around 60ms, so ~3000 samples - soundBufferDesiredSize = - sizeof(int16_t *) * ((((avgFrameTime * 2) >> 10) * soundSampleRate) >> 10); - } - - flushSend(); - return; - } - - if (dataLeft > 0) { - uint32_t transfer = bytesPerTransfer; - if (dataLeft < transfer) - transfer = dataLeft; - auto pixels = queuePkt(displayServiceNum, JD_INDEXED_SCREEN_CMD_SET_PIXELS, transfer); - memcpy(pixels, dataPtr, transfer); - dataPtr += transfer; - dataLeft -= transfer; - flushSend(); - } else if (soundServiceNum && soundBufferPending < soundBufferDesiredSize) { - int bytesLeft = soundBufferDesiredSize - soundBufferPending; - if (bytesLeft > bytesPerTransfer) - bytesLeft = bytesPerTransfer; - auto samples = (int16_t *)queuePkt(soundServiceNum, JD_ARCADE_SOUND_CMD_PLAY, bytesLeft); - if (pxt::redirectSamples(samples, bytesLeft >> 1, soundSampleRate)) { - soundBufferPending += bytesLeft; - } else { - // no sound generated, fill with 0 and stop - memset(samples, 0, bytesLeft); - soundBufferDesiredSize = 0; - } - flushSend(); - } else { - // trigger sendDone(), which executes outside of IRQ context, so there - // is no race with waitForSendDone - Event(DEVICE_ID_DISPLAY, 4243); - } -} - -int JDDisplay::sendIndexedImage(const uint8_t *src, unsigned width, unsigned height, - uint32_t *palette) { - if (height & 1 || !height || !width) - target_panic(123); // PANIC_SCREEN_ERROR - if (width != addr.width || height != addr.height) - target_panic(124); // PANIC_SCREEN_ERROR - if (inProgress) - target_panic(125); // PANIC_SCREEN_ERROR - - if (addr.y && addr.y >= screenHeight) - return 0; // out of range - - inProgress = true; - - int numcols = JD_SERIAL_PAYLOAD_SIZE / (height / 2); - - bytesPerTransfer = numcols * (height / 2); - dataLeft = (height / 2) * width; - dataPtr = src; - - this->palette = palette; - - memset(&sendFrame, 0, sizeof(sendFrame)); - - step(); - - return 0; -} - -} // namespace pxt \ No newline at end of file diff --git a/libs/arcadeshield/jddisplay.h b/libs/arcadeshield/jddisplay.h deleted file mode 100644 index f9626d388be..00000000000 --- a/libs/arcadeshield/jddisplay.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef __JDDISPLAY_H -#define __JDDISPLAY_H - -#include "pxt.h" - -#include "Pin.h" -#define PinCompat codal::Pin - -#undef SPI -#include "jdprotocol.h" -#include "arcadegamepad.h" -#include "indexedscreen.h" -#include "arcadesound.h" - -namespace pxt { - -class JDDisplay { - jd_indexed_screen_start_update_t addr; - SPI *spi; - Pin *cs; - Pin *flow; - uint32_t dataLeft; - const uint8_t *dataPtr; - uint32_t *palette; - jd_frame_t sendFrame; - jd_frame_t recvFrame; - uint8_t bytesPerTransfer; - bool inProgress; - volatile bool stepWaiting; - uint8_t displayServiceNum; - uint8_t controlsStartServiceNum; - uint8_t controlsEndServiceNum; - uint8_t soundServiceNum; - uint16_t screenWidth, screenHeight; - uint32_t buttonState; - uint32_t avgFrameTime; // in us - uint32_t lastFrameTimestamp; - - uint32_t soundBufferDesiredSize; - uint32_t soundBufferPending; - uint16_t soundSampleRate; - - void *queuePkt(uint32_t service_num, uint32_t service_cmd, uint32_t size); - void flushSend(); - void step(); - void sendDone(Event); - static void stepStatic(void *); - void onFlowHi(Event); - void handleIncoming(jd_packet_t *pkt); - - public: - uint8_t brightness; - JDDisplay(SPI *spi, Pin *cs, Pin *flow); - void setAddrWindow(int x, int y, int w, int h) { - addr.x = x; - addr.y = y; - addr.width = w; - addr.height = h; - } - void waitForSendDone(); - - int sendIndexedImage(const uint8_t *src, unsigned width, unsigned height, uint32_t *palette); -}; - -} // namespace pxt - -#endif diff --git a/libs/arcadeshield/jdprotocol.h b/libs/arcadeshield/jdprotocol.h deleted file mode 100644 index 8d81c488e0d..00000000000 --- a/libs/arcadeshield/jdprotocol.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef __JDPROTOCOL_H -#define __JDPROTOCOL_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// 255 minus size of the serial header, rounded down to 4 -#define JD_SERIAL_PAYLOAD_SIZE 236 -#define JD_SERIAL_FULL_HEADER_SIZE 16 - -#define JD_SERVICE_CLASS_CTRL 0x00000000 - -#define JD_SERVICE_NUMBER_CTRL 0x00 -#define JD_SERVICE_NUMBER_MASK 0x3f -#define JD_SERVICE_NUMBER_CRC_ACK 0x3f - -// the COMMAND flag signifies that the device_identifier is the recipent -// (i.e., it's a command for the peripheral); the bit clear means device_identifier is the source -// (i.e., it's a report from peripheral or a broadcast message) -#define JD_FRAME_FLAG_COMMAND 0x01 -// an ACK should be issued with CRC of this package upon reception -#define JD_FRAME_FLAG_ACK_REQUESTED 0x02 -// the device_identifier contains target service class number -#define JD_FRAME_FLAG_IDENTIFIER_IS_SERVICE_CLASS 0x04 - -#define JD_FRAME_SIZE(pkt) ((pkt)->size + 12) - -// Registers 0x001-0x07f - r/w common to all services -// Registers 0x080-0x0ff - r/w defined per-service -// Registers 0x100-0x17f - r/o common to all services -// Registers 0x180-0x1ff - r/o defined per-service -// Registers 0x200-0xeff - custom, defined per-service -// Registers 0xf00-0xfff - reserved for implementation, should not be on the wire - -// this is either binary (0 or non-zero), or can be gradual (eg. brightness of neopixel) -#define JD_REG_INTENSITY 0x01 -// the primary value of actuator (eg. servo angle) -#define JD_REG_VALUE 0x02 -// enable/disable streaming -#define JD_REG_IS_STREAMING 0x03 -// streaming interval in miliseconds -#define JD_REG_STREAMING_INTERVAL 0x04 -// for analog sensors -#define JD_REG_LOW_THRESHOLD 0x05 -#define JD_REG_HIGH_THRESHOLD 0x06 -// limit power drawn; in mA -#define JD_REG_MAX_POWER 0x07 - -// eg. one number for light sensor, all 3 coordinates for accelerometer -#define JD_REG_READING 0x101 - -#define JD_CMD_GET_REG 0x1000 -#define JD_CMD_SET_REG 0x2000 - -#define JD_GET(reg) (JD_CMD_GET_REG | (reg)) -#define JD_SET(reg) (JD_CMD_SET_REG | (reg)) - -// Commands 0x000-0x07f - common to all services -// Commands 0x080-0xeff - defined per-service -// Commands 0xf00-0xfff - reserved for implementation -// enumeration data for CTRL, ad-data for other services -#define JD_CMD_ADVERTISEMENT_DATA 0x00 -// event from sensor or on broadcast service -#define JD_CMD_EVENT 0x01 -// request to calibrate sensor -#define JD_CMD_CALIBRATE 0x02 -// request human-readable description of service -#define JD_CMD_GET_DESCRIPTION 0x03 - -// Commands specific to control service -// do nothing -#define JD_CMD_CTRL_NOOP 0x80 -// blink led or otherwise draw user's attention -#define JD_CMD_CTRL_IDENTIFY 0x81 -// reset device -#define JD_CMD_CTRL_RESET 0x82 -// identifies the type of hardware (eg., ACME Corp. Servo X-42 Rev C) -#define JD_REG_CTRL_DEVICE_DESCRIPTION 0x180 -// a numeric code for the string above; used to mark firmware images -#define JD_REG_CTRL_DEVICE_CLASS 0x181 -// MCU temperature in Celsius -#define JD_REG_CTRL_TEMPERATURE 0x182 -// this is very approximate; ADC reading from backward-biasing the identification LED -#define JD_REG_CTRL_LIGHT_LEVEL 0x183 -// typically the same as JD_REG_CTRL_DEVICE_CLASS; the bootloader will respond to that code -#define JD_REG_CTRL_BL_DEVICE_CLASS 0x184 - -struct _jd_packet_t { - uint16_t crc; - uint8_t _size; // of frame data[] - uint8_t flags; - - uint64_t device_identifier; - - uint8_t service_size; - uint8_t service_number; - uint16_t service_command; - - uint8_t data[0]; -} __attribute__((__packed__, aligned(4))); -typedef struct _jd_packet_t jd_packet_t; - -struct _jd_frame_t { - uint16_t crc; - uint8_t size; - uint8_t flags; - - uint64_t device_identifier; - - uint8_t data[JD_SERIAL_PAYLOAD_SIZE + 4]; -} __attribute__((__packed__, aligned(4))); -typedef struct _jd_frame_t jd_frame_t; - -#define JDSPI_MAGIC 0x7ACD -#define JDSPI_MAGIC_NOOP 0xB3CD - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libs/arcadeshield/pins.cpp b/libs/arcadeshield/pins.cpp deleted file mode 100644 index 01289adf09f..00000000000 --- a/libs/arcadeshield/pins.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "pxt.h" - -#include "Pin.h" -#define PinCompat codal::Pin - -#include "config_nrf.h" - -// #undef Button - -namespace pxt { -static DevicePin **pinPtrs; -static uint8_t numPinPtrs; -static uint8_t pinPos[DEV_NUM_PINS]; - -DevicePin *myGetPin(int id) { - - id &= CFG_PIN_NAME_MSK; - - if (id >= DEV_NUM_PINS) - soft_panic(PANIC_NO_SUCH_PIN); - - // we could use lookupComponent() here - it would be slightly slower - - int ptr = pinPos[id]; - if (ptr == 0) { - pinPtrs = (DevicePin **)realloc(pinPtrs, (numPinPtrs + 1) * sizeof(void *)); - bool isAnalog = IS_ANALOG_PIN(id); - // GCTODO - pinPtrs[numPinPtrs++] = - new DevicePin(DEVICE_ID_IO_P0 + id, (PinName)id, - isAnalog ? PIN_CAPABILITY_AD : PIN_CAPABILITY_DIGITAL); - ptr = numPinPtrs; - pinPos[id] = ptr; - } - return pinPtrs[ptr - 1]; -} - -DevicePin *getPinCfg(int key) { - int p = getConfig(key, -1); - if (p == -1) - DMESG("no pin cfg: %d", key); - return myGetPin(p); -} - -void linkPin(int from, int to) { - if (from < 0 || from >= DEV_NUM_PINS) - soft_panic(PANIC_NO_SUCH_PIN); - myGetPin(to); - pinPos[from] = pinPos[to]; -} - -DevicePin *myLookupPin(int pinName) { - if (pinName < 0 || pinName == 0xff) - return NULL; - pinName &= CFG_PIN_NAME_MSK; - return myGetPin(pinName); -} - -DevicePin *lookupPinCfg(int key) { - return myLookupPin(getConfig(key)); -} - -CodalComponent *lookupComponent(int id) { - for (int i = 0; i < DEVICE_COMPONENT_COUNT; ++i) { - if (CodalComponent::components[i] && CodalComponent::components[i]->id == id) - return CodalComponent::components[i]; - } - return NULL; -} - -} // namespace pxt diff --git a/libs/arcadeshield/pinsDigital.cpp b/libs/arcadeshield/pinsDigital.cpp deleted file mode 100644 index 042a986e1aa..00000000000 --- a/libs/arcadeshield/pinsDigital.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "pxt.h" - -#include "Pin.h" -#define PinCompat codal::Pin - -#include "config_nrf.h" - -namespace pxt { - -static void waitABit() { - // for (int i = 0; i < 10; ++i) - // asm volatile("nop"); -} - -class ButtonMultiplexer : public CodalComponent { - public: - Pin &latch; - Pin &clock; - Pin &data; - uint32_t state; - uint32_t invMask; - uint16_t buttonIdPerBit[8]; - bool enabled; - - ButtonMultiplexer(uint16_t id) - : latch(uBit.io.P9), - clock(uBit.io.P20), - data((uBit.io.P14)) { - this->id = id; - this->status |= DEVICE_COMPONENT_STATUS_SYSTEM_TICK; - - state = 0; - invMask = 0; - enabled = true; - - memset(buttonIdPerBit, 0, sizeof(buttonIdPerBit)); - - data.setPull(PullMode::Down); - data.getDigitalValue(); - latch.setDigitalValue(1); - clock.setDigitalValue(1); - } - - void disable() { - data.getDigitalValue(PullMode::None); - latch.getDigitalValue(PullMode::None); - clock.getDigitalValue(PullMode::None); - enabled = false; - } - - bool isButtonPressed(int id) { - for (int i = 0; i < 8; ++i) { - if (buttonIdPerBit[i] == id) - return (state & (1 << i)) != 0; - } - return false; - } - - uint32_t readBits(int bits) { - latch.setDigitalValue(0); - waitABit(); - latch.setDigitalValue(1); - waitABit(); - - uint32_t state = 0; - for (int i = 0; i < bits; i++) { - state <<= 1; - if (data.getDigitalValue()) - state |= 1; - - clock.setDigitalValue(0); - waitABit(); - clock.setDigitalValue(1); - waitABit(); - } - - return state; - } - - virtual void periodicCallback() override { - if (!enabled) - return; - - uint32_t newState = readBits(8); - newState ^= invMask; - if (newState == state) - return; - - for (int i = 0; i < 8; ++i) { - uint32_t mask = 1 << i; - if (!buttonIdPerBit[i]) - continue; - int ev = 0; - if (!(state & mask) && (newState & mask)) - ev = PXT_INTERNAL_KEY_DOWN; - else if ((state & mask) && !(newState & mask)) - ev = PXT_INTERNAL_KEY_UP; - if (ev) { - Event(ev, buttonIdPerBit[i]); - Event(ev, 0); // any key - } - } - - state = newState; - } -}; - -static ButtonMultiplexer *btnMultiplexer; -ButtonMultiplexer *getMultiplexer() { - if (!btnMultiplexer) - btnMultiplexer = new ButtonMultiplexer(DEVICE_ID_FIRST_BUTTON); - return btnMultiplexer; -} - -int registerMultiplexedButton(int pin, int buttonId) { - if (1050 <= pin && pin < 1058) { - pin -= 50; - getMultiplexer()->invMask |= 1 << (pin - 1000); - } - if (1000 <= pin && pin < 1008) { - getMultiplexer()->buttonIdPerBit[pin - 1000] = buttonId; - return 1; - } - return 0; -} - -int multiplexedButtonIsPressed(int btnId) { - if (btnMultiplexer) - return btnMultiplexer->isButtonPressed(btnId) ? 512 : 0; - return 0; -} - -uint32_t readButtonMultiplexer(int bits) { - return getMultiplexer()->readBits(bits); -} - -void disableButtonMultiplexer() { - getMultiplexer()->disable(); -} - -} - diff --git a/libs/arcadeshield/pxt.json b/libs/arcadeshield/pxt.json deleted file mode 100644 index fac8df78f38..00000000000 --- a/libs/arcadeshield/pxt.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "arcadeshield", - "description": "Support for the Arcade Shield. micro:bit (V2) only.", - "dependencies": { - "core": "file:../core", - "bitmap": "file:../bitmap", - "fonts": "file:../fonts" - }, - "files": [ - "config_nrf.h", - "arcadegamepad.h", - "indexedscreen.h", - "arcadesound.h", - "jdprotocol.h", - "jddisplay.h", - "jddisplay.cpp", - "pins.cpp", - "pinsDigital.cpp", - "controllerbuttons.cpp", - "screen.cpp", - "screenhelpers.d.ts", - "shims.d.ts" - ], - "test": [ - "test.ts" - ], - "public": true, - "hidden": true, - "preferredEditor": "tsprj", - "disablesVariants": [ - "mbdal" - ], - "yotta": { - "config": { - "DEVICE_BLE": 0, - "DMESG_SERIAL_DEBUG": 1 - } - } -} diff --git a/libs/arcadeshield/screen.cpp b/libs/arcadeshield/screen.cpp deleted file mode 100644 index 73078478ab4..00000000000 --- a/libs/arcadeshield/screen.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include "pxt.h" - -#include "Pin.h" -#define PinCompat codal::Pin - -#include "ST7735.h" -#include "ILI9341.h" - -// this is a hack because someone (don't know where) #defined SPI to be NRF52SPI, -// which messes with the include file below the #undef -#undef SPI -#include "SPIScreenIO.h" - -#include "jddisplay.h" - -#include "config_nrf.h" - -typedef RefImage *Bitmap_; - -namespace pxt { - -class WDisplay { - public: - ScreenIO *io; - ST7735 *lcd; - JDDisplay *smart; - - uint32_t currPalette[16]; - bool present; - bool newPalette; - bool inUpdate; - uint8_t *screenBuf; - - uint16_t width, height; - uint16_t displayHeight; - uint8_t offX, offY; - bool doubleSize; - uint32_t palXOR; - - WDisplay() { - uint32_t cfg2 = MY_DISPLAY_CFG2; - - uint32_t cfg0 = MY_DISPLAY_CFG0; - uint32_t frmctr1 = MY_DISPLAY_CFG1; - - int dispTp = MY_DISPLAY_TYPE; - - doubleSize = false; - smart = NULL; - - auto miso = LOOKUP_PIN(DISPLAY_MISO); - dispTp = smartConfigure(&cfg0, &frmctr1, &cfg2); - - if (dispTp != DISPLAY_TYPE_SMART) - miso = NULL; // only JDDisplay needs MISO, otherwise leave free - - SPI *spi = new CODAL_SPI(*LOOKUP_PIN(DISPLAY_MOSI), *miso, *LOOKUP_PIN(DISPLAY_SCK)); - io = new SPIScreenIO(*spi); - - if (dispTp == DISPLAY_TYPE_ST7735) { - width = 160; - height = 128; - lcd = new ST7735(*io, *LOOKUP_PIN(DISPLAY_CS), *LOOKUP_PIN(DISPLAY_DC)); - } else if (dispTp == DISPLAY_TYPE_SMART) { - lcd = NULL; - width = 160; - height = 120; - smart = new JDDisplay(spi, LOOKUP_PIN(DISPLAY_CS), LOOKUP_PIN(DISPLAY_DC)); - } else - target_panic(128); // PANIC_SCREEN_ERROR - - palXOR = (cfg0 & 0x1000000) ? 0xffffff : 0x000000; - auto madctl = cfg0 & 0xff; - offX = (cfg0 >> 8) & 0xff; - offY = (cfg0 >> 16) & 0xff; - - DMESG("configure screen: FRMCTR1=%p MADCTL=%p type=%d", frmctr1, madctl, dispTp); - - if (spi) { - auto freq = (cfg2 & 0xff); - if (!freq) - freq = 15; - spi->setFrequency(freq * 1000000); - spi->setMode(0); - // make sure the SPI peripheral is initialized before toggling reset - spi->write(0); - } - - auto rst = LOOKUP_PIN(DISPLAY_RST); - if (rst) { - rst->setDigitalValue(0); - fiber_sleep(20); - rst->setDigitalValue(1); - fiber_sleep(20); - } - - if (lcd) { - auto bl = LOOKUP_PIN(DISPLAY_BL); - if (bl) { - bl->setDigitalValue(1); - } - - lcd->init(); - lcd->configure(madctl, frmctr1); - } - - displayHeight = height; - setAddrMain(); - DMESG("screen: %d x %d, off=%d,%d", width, height, offX, offY); - int sz = doubleSize ? (width >> 1) * (height >> 1) : width * height; - screenBuf = (uint8_t *)app_alloc(sz / 2 + 20); - inUpdate = false; - } - - uint32_t smartConfigure(uint32_t *cfg0, uint32_t *cfg1, uint32_t *cfg2) { - uint32_t hc; - present = false; - - DMESG("74HC: waiting..."); - - // wait while nothing is connected - for (;;) { - auto rst = LOOKUP_PIN(DISPLAY_RST); - if (rst) { - rst->setDigitalValue(0); - target_wait_us(10); - rst->setDigitalValue(1); - fiber_sleep(3); // in reality we need around 1.2ms - } - - hc = readButtonMultiplexer(17); - if (hc != 0) - break; - - fiber_sleep(100); - - // the device will run without shield when the following is specified in user program: - // namespace userconfig { export const DISPLAY_CFG0 = 0x02000080 } - if (*cfg0 & 0x2000000) { - DMESG("74HC: no wait requested"); - return DISPLAY_TYPE_ST7735; - } - } - present = true; - - DMESG("74HC: %x", hc); - - // is the line forced up? if so, assume JDDisplay - if (hc == 0x1FFFF) { - disableButtonMultiplexer(); - return DISPLAY_TYPE_SMART; - } - - hc = hc >> 1; - - // SER pin (or first bit of second HC) is orientation - if (hc & 0x0010) - *cfg0 = 0x80; - else - *cfg0 = 0x40; - - uint32_t configId = (hc & 0xe0) >> 5; - - - switch (configId) { - case 1: - *cfg1 = 0x0603; // ST7735 - break; - case 2: - *cfg1 = 0xe14ff; // ILI9163C - *cfg0 |= 0x08; // BGR colors - break; - case 3: - *cfg1 = 0x0603; // ST7735 - *cfg0 |= 0x1000000; // inverted colors - break; - default: - target_panic(129); // PANIC_SCREEN_ERROR - break; - } - - DMESG("config type: %d; cfg0=%x cfg1=%x", configId, *cfg0, *cfg1); - - // for some reason, setting SPI frequency to 32 doesn't - // work with ST77735 in pxt-microbit - *cfg2 = 16; // Damn the torpedoes! 32MHz - - return DISPLAY_TYPE_ST7735; - } - - void setAddrMain() { - if (lcd) - lcd->setAddrWindow(offX, offY, width, displayHeight); - else - smart->setAddrWindow(offX, offY, width, displayHeight); - } - void waitForSendDone() { - if (lcd) - lcd->waitForSendDone(); - else - smart->waitForSendDone(); - } - int sendIndexedImage(const uint8_t *src, unsigned width, unsigned height, uint32_t *palette) { - if (lcd) - return lcd->sendIndexedImage(src, width, height, palette); - else - return smart->sendIndexedImage(src, width, height, palette); - } -}; - -SINGLETON_IF_PIN(WDisplay, DISPLAY_MOSI); - -//% -int setScreenBrightnessSupported() { - auto display = getWDisplay(); - if (display && display->smart) - return 1; - - auto bl = LOOKUP_PIN(DISPLAY_BL); - if (!bl) - return 0; -#ifdef SAMD51 - if (bl->name == PA06) - return 0; -#endif -#ifdef NRF52_SERIES - // PWM not implemented yet - return 0; -#else - return 1; -#endif -} - -//% -void setScreenBrightness(int level) { - if (level < 0) - level = 0; - if (level > 100) - level = 100; - - auto display = getWDisplay(); - if (display && display->smart) { - display->smart->brightness = level; - return; - } - - auto bl = LOOKUP_PIN(DISPLAY_BL); - if (!bl) - return; - - if (level == 0) - bl->setDigitalValue(0); - else if (level == 100) - bl->setDigitalValue(1); - else { - if (setScreenBrightnessSupported()) { - bl->setAnalogPeriodUs(1000); - bl->setAnalogValue(level * level * 1023 / 10000); - } - } -} - -//% -void setPalette(Buffer buf) { - auto display = getWDisplay(); - if (!display) - return; - - if (48 != buf->length) - target_panic(130); // PANIC_SCREEN_ERROR - for (int i = 0; i < 16; ++i) { - display->currPalette[i] = - (buf->data[i * 3] << 16) | (buf->data[i * 3 + 1] << 8) | (buf->data[i * 3 + 2] << 0); - display->currPalette[i] ^= display->palXOR; - } - display->newPalette = true; -} - -//% -bool displayPresent() { - auto display = getWDisplay(); - if (!display) - return false; - return display->present; -} - -//% -int displayHeight() { - auto display = getWDisplay(); - if (!display) - return -1; - return display->displayHeight; -} - -//% -int displayWidth() { - auto display = getWDisplay(); - if (!display) - return -1; - return display->width; -} - -//% -void updateScreen(Bitmap_ img) { - auto display = getWDisplay(); - if (!display) - return; - - if (display->inUpdate) - return; - - display->inUpdate = true; - - auto mult = display->doubleSize ? 2 : 1; - - if (img) { - if (img->bpp() != 4 || img->width() * mult != display->width || - img->height() * mult != display->displayHeight) - target_panic(131); // PANIC_SCREEN_ERROR - - // DMESG("wait for done"); - display->waitForSendDone(); - - auto palette = display->currPalette; - - if (display->newPalette) { - display->newPalette = false; - } else { - // smart mode always sends palette - if (!display->smart) - palette = NULL; - } - - memcpy(display->screenBuf, img->pix(), img->pixLength()); - - // DMESG("send"); - display->sendIndexedImage(display->screenBuf, img->width(), img->height(), palette); - } - - display->inUpdate = false; -} - -//% -void updateStats(String msg) { - // ignore... -} - -} // namespace pxt \ No newline at end of file diff --git a/libs/arcadeshield/screenhelpers.d.ts b/libs/arcadeshield/screenhelpers.d.ts deleted file mode 100644 index 7495f5d6c6a..00000000000 --- a/libs/arcadeshield/screenhelpers.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare namespace __screenhelpers { - //% shim=pxt::displayPresent - function displayPresent(): boolean; - //% shim=pxt::setPalette - function setPalette(buf: Buffer): void; - //% shim=pxt::displayWidth - function displayWidth(): number; - //% shim=pxt::displayHeight - function displayHeight(): number; - //% shim=pxt::setScreenBrightness - function setScreenBrightness(b: number): void; - //% shim=pxt::updateScreen - function updateScreen(bmp: Bitmap): void; -} diff --git a/libs/arcadeshield/shims.d.ts b/libs/arcadeshield/shims.d.ts deleted file mode 100644 index 3c20787423c..00000000000 --- a/libs/arcadeshield/shims.d.ts +++ /dev/null @@ -1,159 +0,0 @@ -// Auto-generated. Do not edit. - - -declare interface Bitmap { - /** - * Get underlying buffer - */ - //% property shim=BitmapMethods::__buffer - __buffer: Buffer; - - /** - * Get the width of the bitmap - */ - //% property shim=BitmapMethods::width - width: int32; - - /** - * Get the height of the bitmap - */ - //% property shim=BitmapMethods::height - height: int32; - - /** - * True if the bitmap is monochromatic (black and white) - */ - //% property shim=BitmapMethods::isMono - isMono: boolean; - - /** - * Sets all pixels in the current bitmap from the other bitmap, which has to be of the same size and - * bpp. - */ - //% shim=BitmapMethods::copyFrom - copyFrom(from: Bitmap): void; - - /** - * Set pixel color - */ - //% shim=BitmapMethods::setPixel - setPixel(x: int32, y: int32, c: int32): void; - - /** - * Get a pixel color - */ - //% shim=BitmapMethods::getPixel - getPixel(x: int32, y: int32): int32; - - /** - * Fill entire bitmap with a given color - */ - //% shim=BitmapMethods::fill - fill(c: int32): void; - - /** - * Copy row(s) of pixel from bitmap to buffer (8 bit per pixel). - */ - //% shim=BitmapMethods::getRows - getRows(x: int32, dst: Buffer): void; - - /** - * Copy row(s) of pixel from buffer to bitmap. - */ - //% shim=BitmapMethods::setRows - setRows(x: int32, src: Buffer): void; - - /** - * Return a copy of the current bitmap - */ - //% shim=BitmapMethods::clone - clone(): Bitmap; - - /** - * Flips (mirrors) pixels horizontally in the current bitmap - */ - //% shim=BitmapMethods::flipX - flipX(): void; - - /** - * Flips (mirrors) pixels vertically in the current bitmap - */ - //% shim=BitmapMethods::flipY - flipY(): void; - - /** - * Returns a transposed bitmap (with X/Y swapped) - */ - //% shim=BitmapMethods::transposed - transposed(): Bitmap; - - /** - * Every pixel in bitmap is moved by (dx,dy) - */ - //% shim=BitmapMethods::scroll - scroll(dx: int32, dy: int32): void; - - /** - * Stretches the bitmap horizontally by 100% - */ - //% shim=BitmapMethods::doubledX - doubledX(): Bitmap; - - /** - * Stretches the bitmap vertically by 100% - */ - //% shim=BitmapMethods::doubledY - doubledY(): Bitmap; - - /** - * Replaces one color in an bitmap with another - */ - //% shim=BitmapMethods::replace - replace(from: int32, to: int32): void; - - /** - * Stretches the bitmap in both directions by 100% - */ - //% shim=BitmapMethods::doubled - doubled(): Bitmap; - - /** - * Draw given bitmap on the current bitmap - */ - //% shim=BitmapMethods::drawBitmap - drawBitmap(from: Bitmap, x: int32, y: int32): void; - - /** - * Draw given bitmap with transparent background on the current bitmap - */ - //% shim=BitmapMethods::drawTransparentBitmap - drawTransparentBitmap(from: Bitmap, x: int32, y: int32): void; - - /** - * Check if the current bitmap "collides" with another - */ - //% shim=BitmapMethods::overlapsWith - overlapsWith(other: Bitmap, x: int32, y: int32): boolean; -} -declare namespace bitmaps { - - /** - * Create new bitmap with given content - */ - //% shim=bitmaps::ofBuffer - function ofBuffer(buf: Buffer): Bitmap; - - /** - * Create new empty (transparent) bitmap - */ - //% shim=bitmaps::create - function create(width: int32, height: int32): Bitmap; - - /** - * Double the size of an icon - */ - //% shim=bitmaps::doubledIcon - function doubledIcon(icon: Buffer): Buffer; -} - -// Auto-generated. Do not edit. Really. diff --git a/libs/arcadeshield/test.ts b/libs/arcadeshield/test.ts deleted file mode 100644 index de610e97277..00000000000 --- a/libs/arcadeshield/test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// tests go here; this will not be compiled when this package is used as an extension. - -const present = __screenhelpers.displayPresent(); -basic.showNumber(present ? 1 : 0) - -// set palette before creating screen, which initializes the display -__screenhelpers.setPalette(hex`000000ffffffff2121ff93c4ff8135fff609249ca378dc52003fad87f2ff8e2ec4a4839f5c406ce5cdc491463d000000`) - -const screen = bitmaps.create( - __screenhelpers.displayWidth(), - __screenhelpers.displayHeight() -) - -input.onButtonPressed(Button.A, () => { - screen.fill(2) - screen.drawLine(0,0,100,100,0) - __screenhelpers.updateScreen(screen) -}) - -input.onButtonPressed(Button.B, () => { - screen.fill(4) - screen.drawLine(100,0,0,100,0) - __screenhelpers.updateScreen(screen) -}) - -input.onButtonPressed(Button.AB, () => { - screen.fill(0) - __screenhelpers.updateScreen(screen) -}) diff --git a/pxtarget.json b/pxtarget.json index e211230993f..297b6a3d172 100644 --- a/pxtarget.json +++ b/pxtarget.json @@ -18,7 +18,6 @@ "libs/datalogger", "libs/bitmap", "libs/fonts", - "libs/arcadeshield", "libs/color", "libs/audio-recording" ], diff --git a/targetconfig.json b/targetconfig.json index 99b414f38dc..b53743e9571 100644 --- a/targetconfig.json +++ b/targetconfig.json @@ -485,7 +485,7 @@ "aspectRatio": 3.45 } }, - "microbit-apps/pxt-arcadeshield": { + "microbit-apps/arcadeshield": { "simx": { "sha": "5bac5ff5b80621b53b746e4bbe252e406b992bdb", "devUrl": "http://localhost:3000"