jnjitkoff wrote:
Even if screenshotting isn't feasible on most platforms, it'd be awesome to have a reuseable way to pass images from devices to the watch, either for notification icons, or other imagery.
Is the code easily abstractable?
Yes- the watch end is really simple - it's basically exposing the watch's drawing API through Bluetooth.
There are three commands - clear the screen, fill a rectangle with a single color, fill a rectangle with the following colors.
There's no reason it can't be repurposed to show photos, etc.
I would probably add support for run-length encoding for at least *some* compression.
Here's the important part of the client part:
#define MAGIC 'C'
enum {
CLEAR = 0,
FILL_RECT = 1,
FILL_PIXELS = 2
} commands;
typedef struct _command {
uint8_t magic; // should be MAGIC
uint8_t command;
union _u {
struct _fill {
uint8_t left;
uint8_t top;
uint8_t right;
uint8_t bottom;
color24_t color;
} fill;
struct _pixels {
uint8_t left;
uint8_t top;
uint8_t right;
uint8_t bottom;
color24_t colors[];
} pixels;
} u;
} __attribute__((packed)) command;
void handle_received_bluetooth_data(const uint8_t *buffer) {
pulse_oled_set_brightness(100);
pulse_update_power_down_timer(SLEEP_DELAY);
command *c = (command *)buffer;
if (c->magic==MAGIC) {
switch (c->command) {
case CLEAR: {
pulse_blank_canvas();
}
break;
case FILL_RECT: {
pulse_set_draw_window(c->u.fill.left, c->u.fill.top, c->u.fill.right, c->u.fill.bottom);
int count = (c->u.fill.right-c->u.fill.left+1)*(c->u.fill.bottom-c->u.fill.top+1);
color24_t color = c->u.fill.color;
while (count--)
pulse_draw_point24(color);
}
break;
case FILL_PIXELS: {
pulse_set_draw_window(c->u.pixels.left, c->u.pixels.top, c->u.pixels.right, c->u.pixels.bottom);
int count = (c->u.pixels.right-c->u.pixels.left+1)*(c->u.pixels.bottom-c->u.pixels.top+1);
color24_t *color = c->u.pixels.colors;
while (count--)
pulse_draw_point24(*color++);
}
break;
default:
printf("BAD CMD %d\n",c->command);
break;
}
} else {
printf("BAD MAG %d\n",c->magic);
}
}
..with the callback registered in main_app_init():
void main_app_init() {
....(other stuff)...
pulse_register_callback(ACTION_HANDLE_NON_PULSE_PROTOCOL_BLUETOOTH_DATA, (PulseCallback)&handle_received_bluetooth_data);
}
What the chumby end is doing is reducing the 320x240 RGB565 down to 80x60 of color24_t, then sending the pixmap with two 40x1 pixel requests per scanline to keep the packet size under the limit.