void JDDisplay::step()

in libs/screen---st7735/jddisplay.cpp [220:323]


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 = pxt::getLongSerialNumber();

    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)current_time_us();
            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);
    }
}