So I've been using commandblock's serial library to send screenshots from my desktop to the TI-84+ CE. I want to eventually get the screenshots at 30 fps so that the display of the calculator basically mirrors my computer. I can get smallish screenshots displayed on the calculator at like 3-5 fps, but if I try increasing how fast I send data at the calculator, the calculator doesn't display all the images any smoother. When I increase the size of the image, the calculator also seems to skip a lot more images and slows down how fast it shows the images. Right now I'm using xlib to make a screenshot and Mateos' convimg to convert to a sprite. Then I send the bytes via serial to the calculator.
Is it even possible to increase the "frame rate"?
Code:
Code:
Demo:
Things that I've tried:
▪ Increasing srl_buf size
▪ Setting the baud rate higher
▪ Using the nonblocking version of srl_read(). I couldn't get the regular srl_read() to receive all the data and display images properly. Would getting this to work improve speed?
Commandblockguy said that "it's probably the code copying to the screen that's slowing it down." How would I address that issue if this were the case.
Commandblockguy also suggested using the raw usb library at the usbdrvce branch instead of the serial library to send data; however, I'm having some trouble getting it to send large amounts of data and some question about it.
What kind of transfers/endpoints does the library support? usbdrvce.h has a typedef making bulk, interrupt, and Isochronous transfers usb_ScheduleTransfer. Does this mean that all 3 types use the same function?
When I used pyUSB on my computer, I only saw 2 endpoints, both of which said BULK:
Code:
Does this mean that there are only 2 endpoints available?
Also when I try sending more than 1024 bytes to the calculator, pyUSB only sends 1024 bytes.
Since the above says that the Max Packet Size is 64, I added the following on line 233:
Code:
When I send 1024 + 64 bytes using pyUSB, pyUSB quits writing after 1024 bytes.
Is this a problem with the computer or with the calculator?
The python code:
Code:
Thanks for reading all this.
Is it even possible to increase the "frame rate"?
Code:
Code:
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <tice.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <keypadc.h>
#define usb_callback_data_t usb_device_t
#include <usbdrvce.h>
#include <srldrvce.h>
#include <graphx.h>
/* Include the converted graphics file */
#include "gfx/gfx.h"
uint8_t srl_buf[4000];
/* Handle USB events */
static usb_error_t handle_usb_event(usb_event_t event, void *event_data,
usb_callback_data_t *callback_data) {
/* When a device is connected, or when connected to a computer */
if(event == USB_DEVICE_CONNECTED_EVENT || event == USB_HOST_CONFIGURE_EVENT) {
if(!*callback_data) {
/* Set the USB device */
*callback_data = event_data;
}
}
/* When a device is disconnected */
if(event == USB_DEVICE_DISCONNECTED_EVENT) {
*callback_data = NULL;
}
return USB_SUCCESS;
}
gfx_UninitedSprite(sprite_buffer, oiram_width, oiram_height);
void main(void)
{
usb_error_t usb_error;
srl_error_t srl_error;
usb_device_t usb_device = NULL;
srl_device_t srl;
/* A buffer for internal use by the serial library */
/* Initialize the USB driver with our event handler and the serial device descriptors */
usb_error = usb_Init(handle_usb_event, &usb_device, srl_GetCDCStandardDescriptors(), USB_DEFAULT_INIT_FLAGS);
if(usb_error) goto exit;
/* Wait for a USB device to be connected */
while(!usb_device) {
kb_Scan();
/* Exit if clear is pressed */
if(kb_IsDown(kb_KeyClear)) {
goto exit;
}
/* Handle any USB events that have occured */
usb_HandleEvents();
}
/* Initialize the serial library with the USB device */
srl_error = srl_Init(&srl, usb_device, srl_buf, sizeof(srl_buf), SRL_INTERFACE_ANY);
if(srl_error) goto exit;
/* Clear the homescreen */
os_ClrHome();
/* Print a string */
os_PutStrFull("Initialized USB Successfully!");
/* Initialize graphics drawing */
gfx_Begin();
/* Set the palette for sprites */
gfx_SetPalette(xlibc, sizeof_xlibc, 0);
/* These were set in the image conversion file */
gfx_SetTransparentColor(0);
gfx_FillScreen(255);
do {
/* A buffer to store bytes read by the serial library */
int bytes_read = 0;
kb_Scan();
usb_HandleEvents();
/* If the device was disconnected, exit */
if(!usb_device) break;
bytes_read = srl_Read_Blocking(&srl, oiram_data, sizeof(oiram_data), 600);
/* Only write when bytes were received */
if(bytes_read == sizeof(oiram_data)) {
gfx_Sprite_NoClip(gfx_FlipSpriteX(oiram, sprite_buffer), 60, 60);
}
} while(!kb_IsDown(kb_KeyClear));
/* A transparent sprite allows the background to show */
//gfx_TransparentSprite_NoClip(oiram, 190, 110);
/* End graphics drawing */
gfx_End();
exit:
usb_Cleanup();
}
Demo:
Things that I've tried:
▪ Increasing srl_buf size
▪ Setting the baud rate higher
▪ Using the nonblocking version of srl_read(). I couldn't get the regular srl_read() to receive all the data and display images properly. Would getting this to work improve speed?
Commandblockguy said that "it's probably the code copying to the screen that's slowing it down." How would I address that issue if this were the case.
Commandblockguy also suggested using the raw usb library at the usbdrvce branch instead of the serial library to send data; however, I'm having some trouble getting it to send large amounts of data and some question about it.
What kind of transfers/endpoints does the library support? usbdrvce.h has a typedef making bulk, interrupt, and Isochronous transfers usb_ScheduleTransfer. Does this mean that all 3 types use the same function?
When I used pyUSB on my computer, I only saw 2 endpoints, both of which said BULK:
Code:
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
Does this mean that there are only 2 endpoints available?
Also when I try sending more than 1024 bytes to the calculator, pyUSB only sends 1024 bytes.
Since the above says that the Max Packet Size is 64, I added the following on line 233:
Code:
int length = 1024 + 64;
if (!(buffer = malloc(length))) {
error = USB_ERROR_NO_MEMORY;
break;
}
for (i = 0; i < (int)ceil(length/64.0); i++) {
usb_ScheduleBulkTransfer(usb_GetDeviceEndpoint((usb_device_t)event_data, 0x02), buffer + i*64, 64, handleBulkOut, buffer + i*64);
}
free(buffer);
break;
When I send 1024 + 64 bytes using pyUSB, pyUSB quits writing after 1024 bytes.
Is this a problem with the computer or with the calculator?
The python code:
Code:
#!/usr/bin/python3
import sys
import usb.core
VENDOR_ID = 0x451
PRODUCT_ID = 0xe008
INTERFACE = 0
SETTING = 0
ENDPOINT = 1
device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if device is None:
raise ValueError('Device not found')
# By default, the kernel will claim the device and make it available via
# /dev/usb/hiddevN and /dev/hidrawN which also prevents us
# from communicating otherwise. This removes these kernel devices.
# Yes, it is weird to specify an interface before we get to a configuration.
if device.is_kernel_driver_active(INTERFACE):
print("Detaching kernel driver")
device.detach_kernel_driver(INTERFACE)
# set the active configuration. With no arguments, the first
# configuration will be the active one
device.set_configuration()
configuration = device.get_active_configuration()
interface = configuration[(INTERFACE, SETTING)]
print(configuration)
endpoint = interface[ENDPOINT]
# endpoint = usb.util.find_descriptor(
# interface,
# # match the first OUT endpoint
# custom_match = \
# lambda e: \
# usb.util.endpoint_direction(e.bEndpointAddress) == \
# usb.util.ENDPOINT_OUT)
assert endpoint is not None
print("Writing data")
print(endpoint.write("A"*(1024+64)))
Thanks for reading all this.