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