mirror of
https://github.com/JorjBauer/aiie.git
synced 2025-02-16 14:30:36 +00:00
removed now-obsolete opencv branch
This commit is contained in:
parent
349120a419
commit
7a18fe2171
12
Makefile
12
Makefile
@ -1,30 +1,24 @@
|
||||
LDFLAGS=-L/usr/local/lib
|
||||
|
||||
OPENCVLIBS=-lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_features2d -lopencv_calib3d
|
||||
|
||||
SDLLIBS=-lSDL2
|
||||
|
||||
CXXFLAGS=-Wall -I .. -I . -I apple -I opencv -I sdl -I/usr/local/include/SDL2 -O3 -g
|
||||
CXXFLAGS=-Wall -I .. -I . -I apple -I sdl -I/usr/local/include/SDL2 -O3 -g
|
||||
|
||||
TSRC=cpu.cpp util/testharness.cpp
|
||||
|
||||
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o RingBuffer.o globals.o apple/parallelcard.o apple/fx80.o apple/mockingboard.o apple/sy6522.o apple/ay8910.o
|
||||
|
||||
OPENCVOBJS=opencv/dummy-speaker.o opencv/opencv-display.o opencv/opencv-keyboard.o opencv/opencv-paddles.o opencv/opencv-filemanager.o opencv/aiie.o opencv/opencv-printer.o
|
||||
SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o sdl/sdl-filemanager.o sdl/aiie.o sdl/sdl-printer.o
|
||||
|
||||
ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h
|
||||
|
||||
all: sdl
|
||||
|
||||
opencv: roms $(COMMONOBJS) $(OPENCVOBJS)
|
||||
g++ $(LDFLAGS) $(OPENCVLIBS) -o aiie-opencv $(COMMONOBJS) $(OPENCVOBJS)
|
||||
|
||||
sdl: roms $(COMMONOBJS) $(SDLOBJS)
|
||||
g++ $(LDFLAGS) $(SDLLIBS) $(OPENCVLIBS) -o aiie-sdl $(COMMONOBJS) $(SDLOBJS)
|
||||
g++ $(LDFLAGS) $(SDLLIBS) -o aiie-sdl $(COMMONOBJS) $(SDLOBJS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ */*.o */*~ testharness.basic testharness.verbose testharness.extended aiie-opencv apple/diskii-rom.h apple/applemmu-rom.h apple/parallel-rom.h aiie-sdl
|
||||
rm -f *.o *~ */*.o */*~ testharness.basic testharness.verbose testharness.extended apple/diskii-rom.h apple/applemmu-rom.h apple/parallel-rom.h aiie-sdl
|
||||
|
||||
test: $(TSRC)
|
||||
g++ $(CXXFLAGS) -DBASICTEST $(TSRC) -o testharness.basic
|
||||
|
299
opencv/aiie.cpp
299
opencv/aiie.cpp
@ -1,299 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <curses.h>
|
||||
#include <termios.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "applevm.h"
|
||||
#include "opencv-display.h"
|
||||
#include "opencv-keyboard.h"
|
||||
#include "dummy-speaker.h"
|
||||
#include "opencv-paddles.h"
|
||||
#include "opencv-filemanager.h"
|
||||
#include "opencv-printer.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#include "timeutil.h"
|
||||
|
||||
//#define SHOWFPS
|
||||
//#define SHOWPC
|
||||
//#define DEBUGCPU
|
||||
//#define SHOWMEMPAGE
|
||||
|
||||
static struct timespec nextInstructionTime, startTime;
|
||||
uint64_t hitcount = 0;
|
||||
uint64_t misscount = 0;
|
||||
|
||||
#define NB_ENABLE 1
|
||||
#define NB_DISABLE 0
|
||||
|
||||
int send_rst = 0;
|
||||
|
||||
pthread_t cpuThreadID;
|
||||
|
||||
void sigint_handler(int n)
|
||||
{
|
||||
send_rst = 1;
|
||||
}
|
||||
|
||||
void nonblock(int state)
|
||||
{
|
||||
struct termios ttystate;
|
||||
|
||||
//get the terminal state
|
||||
tcgetattr(STDIN_FILENO, &ttystate);
|
||||
|
||||
if (state==NB_ENABLE)
|
||||
{
|
||||
//turn off canonical mode
|
||||
ttystate.c_lflag &= ~ICANON;
|
||||
//minimum of number input read.
|
||||
ttystate.c_cc[VMIN] = 1;
|
||||
}
|
||||
else if (state==NB_DISABLE)
|
||||
{
|
||||
//turn on canonical mode
|
||||
ttystate.c_lflag |= ICANON;
|
||||
}
|
||||
//set the terminal attributes.
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
|
||||
|
||||
}
|
||||
|
||||
uint8_t read(void *arg, uint16_t address)
|
||||
{
|
||||
// no action; this is a dummy function until we've finished initializing...
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void write(void *arg, uint16_t address, uint8_t v)
|
||||
{
|
||||
// no action; this is a dummy function until we've finished initializing...
|
||||
}
|
||||
|
||||
static void *cpu_thread(void *dummyptr) {
|
||||
struct timespec currentTime;
|
||||
|
||||
#if 0
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
pthread_getschedparam(pthread_self(), &policy, ¶m);
|
||||
param.sched_priority = sched_get_priority_max(policy);
|
||||
pthread_setschedparam(pthread_self(), policy, ¶m);
|
||||
#endif
|
||||
|
||||
_init_darwin_shim();
|
||||
do_gettime(&startTime);
|
||||
do_gettime(&nextInstructionTime);
|
||||
|
||||
printf("free-running\n");
|
||||
while (1) {
|
||||
// cycle down the CPU...
|
||||
do_gettime(¤tTime);
|
||||
struct timespec diff = tsSubtract(nextInstructionTime, currentTime);
|
||||
if (diff.tv_sec >= 0 && diff.tv_nsec >= 0) {
|
||||
hitcount++;
|
||||
nanosleep(&diff, NULL);
|
||||
} else {
|
||||
misscount++;
|
||||
}
|
||||
|
||||
#ifdef DEBUGCPU
|
||||
uint8_t executed = g_cpu->Run(1);
|
||||
#else
|
||||
uint8_t executed = g_cpu->Run(24);
|
||||
#endif
|
||||
timespec_add_cycles(&startTime, g_cpu->cycles + executed, &nextInstructionTime);
|
||||
|
||||
g_speaker->beginMixing();
|
||||
|
||||
// The paddles need to be triggered in real-time on the CPU
|
||||
// clock. That happens from the VM's CPU maintenance poller.
|
||||
((AppleVM *)g_vm)->cpuMaintenance(g_cpu->cycles);
|
||||
|
||||
// cpuMaintenance also maintained the sound card; update the speaker after
|
||||
g_speaker->maintainSpeaker(g_cpu->cycles);
|
||||
|
||||
#ifdef DEBUGCPU
|
||||
{
|
||||
uint8_t p = g_cpu->flags;
|
||||
printf("OP: $%02x A: %02x X: %02x Y: %02x PC: $%04x SP: %02x Flags: %c%cx%c%c%c%c%c\n",
|
||||
g_vm->getMMU()->read(g_cpu->pc),
|
||||
g_cpu->a, g_cpu->x, g_cpu->y, g_cpu->pc, g_cpu->sp,
|
||||
p & (1<<7) ? 'N':' ',
|
||||
p & (1<<6) ? 'V':' ',
|
||||
p & (1<<4) ? 'B':' ',
|
||||
p & (1<<3) ? 'D':' ',
|
||||
p & (1<<2) ? 'I':' ',
|
||||
p & (1<<1) ? 'Z':' ',
|
||||
p & (1<<0) ? 'C':' '
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (send_rst) {
|
||||
#if 1
|
||||
printf("Sending reset\n");
|
||||
g_cpu->Reset();
|
||||
|
||||
// testing startup keyboard presses - perform Apple //e self-test
|
||||
//g_vm->getKeyboard()->keyDepressed(RA);
|
||||
//g_vm->Reset();
|
||||
//g_cpu->Reset();
|
||||
//((AppleVM *)g_vm)->insertDisk(0, "disks/DIAGS.DSK");
|
||||
|
||||
#else
|
||||
MMU *mmu = g_vm->getMMU();
|
||||
|
||||
printf("PC: 0x%X\n", g_cpu->pc);
|
||||
for (int i=g_cpu->pc; i<g_cpu->pc + 0x100; i++) {
|
||||
printf("0x%X ", mmu->read(i));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
||||
printf("Dropping to monitor\n");
|
||||
// drop directly to monitor.
|
||||
g_cpu->pc = 0xff69; // "call -151"
|
||||
mmu->read(0xC054); // make sure we're in page 1
|
||||
mmu->read(0xC056); // and that hires is off
|
||||
mmu->read(0xC051); // and text mode is on
|
||||
mmu->read(0xC08A); // and we have proper rom in place
|
||||
mmu->read(0xc008); // main zero-page
|
||||
mmu->read(0xc006); // rom from cards
|
||||
mmu->write(0xc002 + mmu->read(0xc014)? 1 : 0, 0xff); // make sure aux ram read and write match
|
||||
mmu->write(0x20, 0); // text window
|
||||
mmu->write(0x21, 40);
|
||||
mmu->write(0x22, 0);
|
||||
mmu->write(0x23, 24);
|
||||
mmu->write(0x33, '>');
|
||||
mmu->write(0x48, 0); // from 0xfb2f: part of text init
|
||||
#endif
|
||||
|
||||
send_rst = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
g_speaker = new DummySpeaker();
|
||||
g_printer = new OpenCVPrinter();
|
||||
|
||||
// create the filemanager - the interface to the host file system.
|
||||
g_filemanager = new OpenCVFileManager();
|
||||
|
||||
// Construct the interface to the host display. This will need the
|
||||
// VM's video buffer in order to draw the VM, but we don't have that
|
||||
// yet. (The OpenCV display looks it up dynamically every blit() call, which
|
||||
// we'll probably change as we get the Teensy version working.)
|
||||
g_display = new OpenCVDisplay();
|
||||
|
||||
// paddles have to be created after g_display created the window
|
||||
g_paddles = new OpenCVPaddles();
|
||||
|
||||
// Next create the virtual CPU. This needs the VM's MMU in order to run, but we don't have that yet.
|
||||
g_cpu = new Cpu();
|
||||
|
||||
// Create the virtual machine. This may read from g_filemanager to get ROMs if necessary.
|
||||
// (The actual Apple VM we've built has them compiled in, though.) It will create its virutal
|
||||
// hardware (MMU, video driver, floppy, paddles, whatever).
|
||||
g_vm = new AppleVM();
|
||||
|
||||
g_keyboard = new OpenCVKeyboard(g_vm->getKeyboard());
|
||||
|
||||
// Now that the VM exists and it has created an MMU, we tell the CPU how to access memory through the MMU.
|
||||
g_cpu->SetMMU(g_vm->getMMU());
|
||||
|
||||
// Now that all the virtual hardware is glued together, reset the VM
|
||||
g_vm->Reset();
|
||||
g_cpu->rst();
|
||||
|
||||
// g_display->blit();
|
||||
g_display->redraw();
|
||||
|
||||
if (argc >= 2) {
|
||||
printf("Inserting disk %s\n", argv[1]);
|
||||
((AppleVM *)g_vm)->insertDisk(0, argv[1]);
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
printf("Inserting disk %s\n", argv[2]);
|
||||
((AppleVM *)g_vm)->insertDisk(1, argv[2]);
|
||||
}
|
||||
|
||||
nonblock(NB_ENABLE);
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
printf("creating CPU thread\n");
|
||||
if (!pthread_create(&cpuThreadID, NULL, &cpu_thread, (void *)NULL)) {
|
||||
printf("thread created\n");
|
||||
// pthread_setschedparam(cpuThreadID, SCHED_RR, PTHREAD_MAX_PRIORITY);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
static uint8_t ctr = 0;
|
||||
if (++ctr == 0) {
|
||||
printf("hit: %llu; miss: %llu; pct: %f\n", hitcount, misscount, (double)misscount / (double)(misscount + hitcount));
|
||||
}
|
||||
|
||||
// Make this a little friendlier, and the expense of some framerate?
|
||||
// usleep(10000);
|
||||
if (g_vm->vmdisplay->needsRedraw()) {
|
||||
AiieRect what = g_vm->vmdisplay->getDirtyRect();
|
||||
// make sure to clear the flag before drawing; there's no lock
|
||||
// on didRedraw, so the other thread might update it
|
||||
g_vm->vmdisplay->didRedraw();
|
||||
g_display->blit(what);
|
||||
}
|
||||
|
||||
g_keyboard->maintainKeyboard();
|
||||
|
||||
g_display->drawBatteryStatus(100);
|
||||
|
||||
#ifdef SHOWFPS
|
||||
static time_t startAt = time(NULL);
|
||||
static uint32_t loopCount = 0;
|
||||
loopCount++;
|
||||
|
||||
time_t lenSecs = time(NULL) - startAt;
|
||||
if (lenSecs >= 10) {
|
||||
char buf[25];
|
||||
sprintf(buf, "%lu FPS", loopCount / lenSecs);
|
||||
g_display->debugMsg(buf);
|
||||
if (lenSecs >= 60) {
|
||||
startAt = time(NULL);
|
||||
loopCount = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef SHOWPC
|
||||
{
|
||||
char buf[25];
|
||||
sprintf(buf, "%X", g_cpu->pc);
|
||||
g_display->debugMsg(buf);
|
||||
}
|
||||
#endif
|
||||
#ifdef SHOWMEMPAGE
|
||||
{
|
||||
char buf[40];
|
||||
sprintf(buf, "AUX %c/%c BNK %d BSR %c/%c ZP %c 80 %c INT %c",
|
||||
g_vm->auxRamRead?'R':'_',
|
||||
g_vm->auxRamWrite?'W':'_',
|
||||
g_vm->bank1,
|
||||
g_vm->readbsr ? 'R':'_',
|
||||
g_vm->writebsr ? 'W':'_',
|
||||
g_vm->altzp ? 'Y':'_',
|
||||
g_vm->_80store ? 'Y' : '_',
|
||||
g_vm->intcxrom ? 'Y' : '_');
|
||||
g_display->debugMsg(buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
#include "dummy-speaker.h"
|
||||
#include <pthread.h>
|
||||
|
||||
DummySpeaker::DummySpeaker()
|
||||
{
|
||||
}
|
||||
|
||||
DummySpeaker::~DummySpeaker()
|
||||
{
|
||||
}
|
||||
|
||||
void DummySpeaker::toggle()
|
||||
{
|
||||
}
|
||||
|
||||
void DummySpeaker::maintainSpeaker(uint32_t c)
|
||||
{
|
||||
}
|
||||
|
||||
void DummySpeaker::beginMixing()
|
||||
{
|
||||
}
|
||||
|
||||
void DummySpeaker::mixOutput(uint8_t v)
|
||||
{
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#ifndef __DUMMYSPEAKER_H
|
||||
#define __DUMMYSPEAKER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "physicalspeaker.h"
|
||||
|
||||
class DummySpeaker : public PhysicalSpeaker {
|
||||
public:
|
||||
DummySpeaker();
|
||||
virtual ~DummySpeaker();
|
||||
|
||||
virtual void toggle();
|
||||
virtual void maintainSpeaker(uint32_t c);
|
||||
virtual void beginMixing();
|
||||
virtual void mixOutput(uint8_t v);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,269 +0,0 @@
|
||||
#include <ctype.h> // isgraph
|
||||
#include "opencv-display.h"
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
#define WINDOWNAME "Aiie!"
|
||||
|
||||
#include "bios-font.h"
|
||||
#include "display-bg.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "applevm.h"
|
||||
|
||||
// RGB map of each of the lowres colors
|
||||
const uint8_t loresPixelColors[16][3] = { { 0, 0, 0 }, // black
|
||||
{ 195, 0, 48 }, // magenta
|
||||
{ 0, 0, 130 }, // dark blue
|
||||
{ 166, 52, 170 }, // purple
|
||||
{ 0, 146, 0 }, // dark green
|
||||
{ 105, 105, 105 }, // drak grey
|
||||
{ 24, 113, 255 }, // medium blue
|
||||
{ 12, 190, 235 }, // light blue
|
||||
{ 150, 85, 40 }, // brown
|
||||
{ 255, 24, 44 }, // orange
|
||||
{ 150, 170, 170 }, // light gray
|
||||
{ 255, 158, 150 }, // pink
|
||||
{ 0, 255, 0 }, // green
|
||||
{ 255, 255, 0 }, // yellow
|
||||
{ 130, 255, 130 }, // aqua
|
||||
{ 255, 255, 255 } // white
|
||||
};
|
||||
|
||||
OpenCVDisplay::OpenCVDisplay()
|
||||
{
|
||||
pixels = new Mat(240*2, 320*2, CV_8UC3);
|
||||
|
||||
namedWindow(WINDOWNAME, CV_WINDOW_AUTOSIZE);
|
||||
}
|
||||
|
||||
OpenCVDisplay::~OpenCVDisplay()
|
||||
{
|
||||
delete pixels; pixels = NULL;
|
||||
}
|
||||
|
||||
void OpenCVDisplay::redraw()
|
||||
{
|
||||
// primarily for the device, where it's in and out of the
|
||||
// bios. Draws the background image.
|
||||
|
||||
for (int y=0; y<240; y++) {
|
||||
for (int x=0; x<320; x++) {
|
||||
uint8_t *p = &displayBitmap[(y * 320 + x)*3];
|
||||
drawPixel(x, y, p[0], p[1], p[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_vm) {
|
||||
drawDriveDoor(0, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
drawDriveDoor(1, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawDriveStatus(uint8_t which, bool isRunning)
|
||||
{
|
||||
// location of status indicator for left drive
|
||||
uint16_t xoff = 125;
|
||||
uint16_t yoff = 213;
|
||||
|
||||
// and right drive
|
||||
if (which == 1)
|
||||
xoff += 135;
|
||||
|
||||
for (int y=0; y<1; y++) {
|
||||
for (int x=0; x<6; x++) {
|
||||
drawPixel(x + xoff, y + yoff, isRunning ? 0xF800 : 0x8AA9);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawDriveDoor(uint8_t which, bool isOpen)
|
||||
{
|
||||
// location of drive door for left drive
|
||||
uint16_t xoff = 55;
|
||||
uint16_t yoff = 216;
|
||||
|
||||
// location for right drive
|
||||
if (which == 1) {
|
||||
xoff += 134;
|
||||
}
|
||||
|
||||
for (int y=0; y<20; y++) {
|
||||
for (int x=0; x<43; x++) {
|
||||
uint8_t *p = &driveLatch[(y * 43 + x)*3];
|
||||
if (isOpen) {
|
||||
p = &driveLatchOpen[(y * 43 + x)*3];
|
||||
}
|
||||
drawPixel(x+xoff, y+yoff, p[0], p[1], p[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawBatteryStatus(uint8_t percent)
|
||||
{
|
||||
uint16_t xoff = 300;
|
||||
uint16_t yoff = 222;
|
||||
|
||||
// the area around the apple is 12 wide
|
||||
// it's exactly 11 high
|
||||
// the color is 210/202/159
|
||||
|
||||
float watermark = ((float)percent / 100.0) * 11;
|
||||
|
||||
for (int y=0; y<11; y++) {
|
||||
uint8_t bgr = 210;
|
||||
uint8_t bgg = 202;
|
||||
uint8_t bgb = 159;
|
||||
|
||||
if (11-y > watermark) {
|
||||
// black...
|
||||
bgr = bgg = bgb = 0;
|
||||
}
|
||||
|
||||
for (int x=0; x<11; x++) {
|
||||
uint8_t *p = &appleBitmap[(y * 10 + (x-1))*4];
|
||||
// It's RGBA; blend w/ background color
|
||||
|
||||
uint8_t r,g,b;
|
||||
float alpha = (float)p[3] / 255.0;
|
||||
r = (float)p[0] * alpha + (bgr * (1.0 - alpha));
|
||||
g = (float)p[1] * alpha + (bgg * (1.0 - alpha));
|
||||
b = (float)p[2] * alpha + (bgb * (1.0 - alpha));
|
||||
drawPixel(x+xoff, y+yoff, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define BASEX 36
|
||||
#define BASEY 26
|
||||
|
||||
void OpenCVDisplay::blit(AiieRect r)
|
||||
{
|
||||
uint8_t *videoBuffer = g_vm->videoBuffer; // FIXME: poking deep
|
||||
for (uint8_t y=r.top; y<=r.bottom; y++) {
|
||||
for (uint16_t x=r.left; x<=r.right; x++) {
|
||||
uint16_t pixel = (y*320+x)/2;
|
||||
uint8_t colorIdx;
|
||||
if (x & 1) {
|
||||
colorIdx = videoBuffer[pixel] & 0x0F;
|
||||
} else {
|
||||
colorIdx = videoBuffer[pixel] >> 4;
|
||||
}
|
||||
|
||||
// OpenCV is using BGR. This pixel-doubles both axes.
|
||||
for (uint8_t xoff=0; xoff<2; xoff++) {
|
||||
for (uint8_t yoff=0; yoff<2; yoff++) {
|
||||
pixels->at<uchar>(y*2+yoff+BASEY, (x*2+xoff+BASEX)*3 + 0) = (loresPixelColors[colorIdx][2]) & 0xFF;
|
||||
pixels->at<uchar>(y*2+yoff+BASEY, (x*2+xoff+BASEX)*3 + 1) = (loresPixelColors[colorIdx][1]) & 0xFF;
|
||||
pixels->at<uchar>(y*2+yoff+BASEY, (x*2+xoff+BASEX)*3 + 2) = (loresPixelColors[colorIdx][0]) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayMessage[0]) {
|
||||
drawString(M_SELECTDISABLED, 1, 240 - 16 - 12, overlayMessage);
|
||||
}
|
||||
|
||||
|
||||
imshow(WINDOWNAME, *pixels);
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawPixel(uint16_t x, uint8_t y, uint16_t color)
|
||||
{
|
||||
uint8_t
|
||||
r = (color & 0xF800) >> 8,
|
||||
g = (color & 0x7E0) >> 3,
|
||||
b = (color & 0x1F) << 3;
|
||||
|
||||
// Pixel-doubling
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
pixels->at<uchar>(y*2+yoff, (x*2+xoff)*3 + 0) = b;
|
||||
pixels->at<uchar>(y*2+yoff, (x*2+xoff)*3 + 1) = g;
|
||||
pixels->at<uchar>(y*2+yoff, (x*2+xoff)*3 + 2) = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawPixel(uint16_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// Pixel-doubling
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
pixels->at<uchar>(y*2+yoff, (x*2+xoff)*3 + 0) = b;
|
||||
pixels->at<uchar>(y*2+yoff, (x*2+xoff)*3 + 1) = g;
|
||||
pixels->at<uchar>(y*2+yoff, (x*2+xoff)*3 + 2) = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
||||
{
|
||||
int8_t xsize = 8,
|
||||
ysize = 0x0C,
|
||||
offset = 0x20;
|
||||
uint16_t temp;
|
||||
|
||||
c -= offset;// font starts with a space
|
||||
|
||||
uint16_t offPixel, onPixel;
|
||||
switch (mode) {
|
||||
case M_NORMAL:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0010;
|
||||
break;
|
||||
case M_SELECTED:
|
||||
onPixel = 0x0000;
|
||||
offPixel = 0xFFFF;
|
||||
break;
|
||||
case M_DISABLED:
|
||||
default:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
case M_SELECTDISABLED:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0xFFE0;
|
||||
break;
|
||||
}
|
||||
|
||||
temp=(c*ysize);
|
||||
for (int8_t y_off = 0; y_off <= ysize; y_off++) {
|
||||
uint8_t ch = BiosFont[temp];
|
||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||
if (ch & (1 << (7-x_off))) {
|
||||
drawPixel(x + x_off, y + y_off, onPixel);
|
||||
} else {
|
||||
drawPixel(x + x_off, y + y_off, offPixel);
|
||||
}
|
||||
}
|
||||
temp++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OpenCVDisplay::drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str)
|
||||
{
|
||||
int8_t xsize = 8; // width of a char in this font
|
||||
|
||||
for (int8_t i=0; i<strlen(str); i++) {
|
||||
drawCharacter(mode, x, y, str[i]);
|
||||
x += xsize; // fixme: any inter-char spacing?
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVDisplay::debugMsg(const char *msg)
|
||||
{
|
||||
printf("%s\n", msg);
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
#ifndef __OPENCV_DISPLAY_H
|
||||
#define __OPENCV_DISPLAY_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
#include "physicaldisplay.h"
|
||||
|
||||
enum {
|
||||
M_NORMAL = 0,
|
||||
M_SELECTED = 1,
|
||||
M_DISABLED = 2,
|
||||
M_SELECTDISABLED = 3
|
||||
};
|
||||
|
||||
class OpenCVDisplay : public PhysicalDisplay {
|
||||
public:
|
||||
OpenCVDisplay();
|
||||
virtual ~OpenCVDisplay();
|
||||
|
||||
virtual void blit(AiieRect r);
|
||||
virtual void redraw();
|
||||
|
||||
virtual void drawDriveDoor(uint8_t which, bool isOpen);
|
||||
virtual void drawDriveStatus(uint8_t which, bool isRunning);
|
||||
virtual void drawBatteryStatus(uint8_t percent);
|
||||
|
||||
void drawPixel(uint16_t x, uint8_t y, uint16_t color);
|
||||
void drawPixel(uint16_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c);
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str);
|
||||
virtual void debugMsg(const char *msg);
|
||||
|
||||
private:
|
||||
|
||||
cv::Mat *pixels;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,189 +0,0 @@
|
||||
#include <string.h> // strcpy
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "opencv-filemanager.h"
|
||||
|
||||
|
||||
OpenCVFileManager::OpenCVFileManager()
|
||||
{
|
||||
numCached = 0;
|
||||
}
|
||||
|
||||
OpenCVFileManager::~OpenCVFileManager()
|
||||
{
|
||||
}
|
||||
|
||||
int8_t OpenCVFileManager::openFile(const char *name)
|
||||
{
|
||||
// See if there's a hole to re-use...
|
||||
for (int i=0; i<numCached; i++) {
|
||||
if (cachedNames[i][0] == '\0') {
|
||||
strncpy(cachedNames[i], name, MAXPATH-1);
|
||||
cachedNames[i][MAXPATH-1] = '\0'; // safety: ensure string terminator
|
||||
fileSeekPositions[i] = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// check for too many open files
|
||||
if (numCached >= MAXFILES)
|
||||
return -1;
|
||||
|
||||
|
||||
// No, so we'll add it to the end
|
||||
strncpy(cachedNames[numCached], name, MAXPATH-1);
|
||||
cachedNames[numCached][MAXPATH-1] = '\0'; // safety: ensure string terminator
|
||||
fileSeekPositions[numCached] = 0;
|
||||
|
||||
numCached++;
|
||||
return numCached-1;
|
||||
}
|
||||
|
||||
void OpenCVFileManager::closeFile(int8_t fd)
|
||||
{
|
||||
// invalid fd provided?
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return;
|
||||
|
||||
// clear the name
|
||||
cachedNames[fd][0] = '\0';
|
||||
}
|
||||
|
||||
const char *OpenCVFileManager::fileName(int8_t fd)
|
||||
{
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return NULL;
|
||||
|
||||
return cachedNames[fd];
|
||||
}
|
||||
|
||||
int8_t OpenCVFileManager::readDir(const char *where, const char *suffix, char *outputFN, int8_t startIdx, uint16_t maxlen)
|
||||
{
|
||||
// not used in this version
|
||||
return -1;
|
||||
}
|
||||
|
||||
void OpenCVFileManager::seekBlock(int8_t fd, uint16_t block, bool isNib)
|
||||
{
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return;
|
||||
|
||||
if (isNib) {
|
||||
fileSeekPositions[fd] = block * 416;
|
||||
} else {
|
||||
fileSeekPositions[fd] = block * 256;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool OpenCVFileManager::readTrack(int8_t fd, uint8_t *toWhere, bool isNib)
|
||||
{
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return false;
|
||||
|
||||
if (cachedNames[fd][0] == 0)
|
||||
return false;
|
||||
|
||||
// open, seek, read, close.
|
||||
bool ret = false;
|
||||
int ffd = open(cachedNames[fd], O_RDONLY);
|
||||
if (ffd) {
|
||||
lseek(ffd, fileSeekPositions[fd], SEEK_SET);
|
||||
if (isNib) {
|
||||
ret = (read(ffd, toWhere, 0x1A00) == 0x1A00);
|
||||
} else {
|
||||
ret = (read(ffd, toWhere, 256 * 16) == 256 * 16);
|
||||
}
|
||||
close(ffd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OpenCVFileManager::readBlock(int8_t fd, uint8_t *toWhere, bool isNib)
|
||||
{
|
||||
// open, seek, read, close.
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return false;
|
||||
|
||||
if (cachedNames[fd][0] == 0)
|
||||
return false;
|
||||
|
||||
// open, seek, read, close.
|
||||
bool ret = false;
|
||||
int ffd = open(cachedNames[fd], O_RDONLY);
|
||||
if (ffd) {
|
||||
lseek(ffd, fileSeekPositions[fd], SEEK_SET);
|
||||
if (isNib) {
|
||||
ret = (read(ffd, toWhere, 416) == 416);
|
||||
} else {
|
||||
ret = (read(ffd, toWhere, 256) == 256);
|
||||
}
|
||||
close(ffd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OpenCVFileManager::writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||
{
|
||||
// open, seek, write, close.
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return false;
|
||||
|
||||
if (cachedNames[fd][0] == 0)
|
||||
return false;
|
||||
|
||||
// don't know how to do this without seeking through the nibblized
|
||||
// track data, so just give up for now
|
||||
if (isNib)
|
||||
return false;
|
||||
|
||||
// open, seek, write, close.
|
||||
int ffd = open(cachedNames[fd], O_WRONLY);
|
||||
if (ffd) {
|
||||
if (lseek(ffd, fileSeekPositions[fd], SEEK_SET) != fileSeekPositions[fd]) {
|
||||
printf("ERROR: failed to seek to %lu\n", fileSeekPositions[fd]);
|
||||
return false;
|
||||
}
|
||||
if (write(ffd, fromWhere, 256) != 256) {
|
||||
printf("ERROR: failed to write 256 bytes\n");
|
||||
return false;
|
||||
}
|
||||
close(ffd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenCVFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||
{
|
||||
// open, seek, write, close.
|
||||
if (fd < 0 || fd >= numCached)
|
||||
return false;
|
||||
|
||||
if (cachedNames[fd][0] == 0)
|
||||
return false;
|
||||
|
||||
// open, seek, write, close.
|
||||
int ffd = open(cachedNames[fd], O_WRONLY);
|
||||
if (ffd) {
|
||||
if (lseek(ffd, fileSeekPositions[fd], SEEK_SET) != fileSeekPositions[fd]) {
|
||||
printf("ERROR: failed to seek to %lu\n", fileSeekPositions[fd]);
|
||||
return false;
|
||||
}
|
||||
int16_t wrsize = 256 * 16;
|
||||
if (isNib)
|
||||
wrsize = 0x1A00;
|
||||
|
||||
if (write(ffd, fromWhere, wrsize) != wrsize) {
|
||||
printf("ERROR: failed to write bytes\n");
|
||||
return false;
|
||||
}
|
||||
close(ffd);
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef __OPENCV_FILEMANAGER_H
|
||||
#define __OPENCV_FILEMANAGER_H
|
||||
|
||||
#include "filemanager.h"
|
||||
#include <stdint.h>
|
||||
|
||||
class OpenCVFileManager : public FileManager {
|
||||
public:
|
||||
OpenCVFileManager();
|
||||
virtual ~OpenCVFileManager();
|
||||
|
||||
virtual int8_t openFile(const char *name);
|
||||
virtual void closeFile(int8_t fd);
|
||||
|
||||
virtual const char *fileName(int8_t fd);
|
||||
|
||||
virtual int8_t readDir(const char *where, const char *suffix, char *outputFN, int8_t startIdx, uint16_t maxlen);
|
||||
virtual void seekBlock(int8_t fd, uint16_t block, bool isNib = false);
|
||||
virtual bool readTrack(int8_t fd, uint8_t *toWhere, bool isNib = false);
|
||||
virtual bool readBlock(int8_t fd, uint8_t *toWhere, bool isNib = false);
|
||||
virtual bool writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
||||
virtual bool writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib = false);
|
||||
|
||||
private:
|
||||
int8_t numCached;
|
||||
char cachedNames[MAXFILES][MAXPATH];
|
||||
unsigned long fileSeekPositions[MAXFILES];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,223 +0,0 @@
|
||||
#include "opencv-keyboard.h"
|
||||
|
||||
/*
|
||||
* OpenCV doesn't support very sophisticated keyboard interaction.
|
||||
* You can't query modifier keys; you don't get up-and-down
|
||||
* events. There's just a simple "has any key been pressed" method.
|
||||
*/
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
OpenCVKeyboard::OpenCVKeyboard(VMKeyboard *k) : PhysicalKeyboard(k)
|
||||
{
|
||||
}
|
||||
|
||||
OpenCVKeyboard::~OpenCVKeyboard()
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int8_t actualKey;
|
||||
bool shifted;
|
||||
} keymapChar;
|
||||
|
||||
// keymap starts at space (32), ends at delete (127).
|
||||
// Note that this maps them based on what the Apple //e expects. It's the
|
||||
// same as a modern US keyboard.
|
||||
const keymapChar keymap[96] =
|
||||
{ { ' ', false }, // space
|
||||
{ '1', true }, // !
|
||||
{ '\'', true }, // "
|
||||
{ '3', true }, // #
|
||||
{ '4', true }, // $
|
||||
{ '5', true }, // %
|
||||
{ '7', true }, // &
|
||||
{ '\'', false}, // '
|
||||
{ '9', true }, // (
|
||||
{ '0', true }, // )
|
||||
{ '8', true }, // *
|
||||
{ '=', true }, // +
|
||||
{ ',', false }, // ,
|
||||
{ '-', false }, // -
|
||||
{ '.', false }, // .
|
||||
{ '/', false }, // /
|
||||
{ '0', false }, // 0
|
||||
{ '1', false }, // 1
|
||||
{ '2', false }, // 2
|
||||
{ '3', false }, // 3
|
||||
{ '4', false }, // 4
|
||||
{ '5', false }, // 5
|
||||
{ '6', false }, // 6
|
||||
{ '7', false }, // 7
|
||||
{ '8', false }, // 8
|
||||
{ '9', false }, // 9
|
||||
{ ':', true }, // :
|
||||
{ ';', false }, // ;
|
||||
{ ',', true }, // <
|
||||
{ '=', false }, // =
|
||||
{ '.', true }, // >
|
||||
{ '/', true }, // ?
|
||||
{ '2', true }, // @
|
||||
{ 'A', true }, // A
|
||||
{ 'B', true }, // B
|
||||
{ 'C', true }, // C
|
||||
{ 'D', true }, // D
|
||||
{ 'E', true }, // E
|
||||
{ 'F', true }, // F
|
||||
{ 'G', true }, // G
|
||||
{ 'H', true }, // H
|
||||
{ 'I', true }, // I
|
||||
{ 'J', true }, // J
|
||||
{ 'K', true }, // K
|
||||
{ 'L', true }, // L
|
||||
{ 'M', true }, // M
|
||||
{ 'N', true }, // N
|
||||
{ 'O', true }, // O
|
||||
{ 'P', true }, // P
|
||||
{ 'Q', true }, // Q
|
||||
{ 'R', true }, // R
|
||||
{ 'S', true }, // S
|
||||
{ 'T', true }, // T
|
||||
{ 'U', true }, // U
|
||||
{ 'V', true }, // V
|
||||
{ 'W', true }, // W
|
||||
{ 'X', true }, // X
|
||||
{ 'Y', true }, // Y
|
||||
{ 'Z', true }, // Z
|
||||
#ifndef TEENSYDUINO
|
||||
{ LA, false }, // [
|
||||
#else
|
||||
{ '[', false }, // [
|
||||
#endif
|
||||
{ '\\', false}, // \ ...
|
||||
#ifndef TEENSYDUINO
|
||||
{ RA, false }, // ]
|
||||
#else
|
||||
{ ']', false }, // ]
|
||||
#endif
|
||||
{ '6', true }, // ^
|
||||
{ '-', true }, // _
|
||||
{ '`', false }, // `
|
||||
{ 'A', false }, // a
|
||||
{ 'B', false }, // b
|
||||
{ 'C', false }, // c
|
||||
{ 'D', false }, // d
|
||||
{ 'E', false }, // e
|
||||
{ 'F', false }, // f
|
||||
{ 'G', false }, // g
|
||||
{ 'H', false }, // h
|
||||
{ 'I', false }, // i
|
||||
{ 'J', false }, // j
|
||||
{ 'K', false }, // k
|
||||
{ 'L', false }, // l
|
||||
{ 'M', false }, // m
|
||||
{ 'N', false }, // n
|
||||
{ 'O', false }, // o
|
||||
{ 'P', false }, // p
|
||||
{ 'Q', false }, // q
|
||||
{ 'R', false }, // r
|
||||
{ 'S', false }, // s
|
||||
{ 'T', false }, // t
|
||||
{ 'U', false }, // u
|
||||
{ 'V', false }, // v
|
||||
{ 'W', false }, // w
|
||||
{ 'X', false }, // x
|
||||
{ 'Y', false }, // y
|
||||
{ 'Z', false }, // z
|
||||
{ '[', true }, // {
|
||||
{ '\\', true }, // |
|
||||
{ ']', true }, // }
|
||||
{ '`', true }, // ~
|
||||
{ DEL, false } // delete
|
||||
};
|
||||
|
||||
void OpenCVKeyboard::maintainKeyboard()
|
||||
{
|
||||
static int invalidCount = 0;
|
||||
int c = cv::waitKey(1);
|
||||
// OpenCV relies on KeyRepeat to deliver individual presses. We want
|
||||
// to guess about "it's still down": so, unless we get > 3 invalid
|
||||
// "-1" values in a row, we're gonna assume it's still pressed.
|
||||
if (c == -1) {
|
||||
invalidCount++;
|
||||
if (invalidCount < 4) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
invalidCount = 0;
|
||||
}
|
||||
|
||||
if (c == -1) {
|
||||
if (lastKey >= ' ' && lastKey <= 127) {
|
||||
vmkeyboard->keyReleased(keymap[lastKey-' '].actualKey);
|
||||
if (keymap[lastKey-' '].shifted) {
|
||||
vmkeyboard->keyReleased(LSHFT);
|
||||
}
|
||||
} else {
|
||||
vmkeyboard->keyReleased(lastKey);
|
||||
}
|
||||
|
||||
lastKey = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (c == 0xF700) {
|
||||
c = UARR; // up
|
||||
} else if (c == 0xF701) {
|
||||
c = DARR; // down
|
||||
} else if (c == 0xF702) {
|
||||
c = LARR; // left
|
||||
} else if (c == 0xF703) {
|
||||
c = RARR; // right
|
||||
}
|
||||
|
||||
// If we're already repeating this key, do nothing
|
||||
if (lastKey != -1 &&
|
||||
lastKey == c) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's a different key, then do a key up
|
||||
if (lastKey != -1) {
|
||||
if (lastKey >= ' ' && lastKey <= 127) {
|
||||
vmkeyboard->keyReleased(keymap[lastKey-' '].actualKey);
|
||||
if (keymap[lastKey-' '].shifted) {
|
||||
vmkeyboard->keyReleased(LSHFT);
|
||||
}
|
||||
} else {
|
||||
vmkeyboard->keyReleased(lastKey);
|
||||
}
|
||||
|
||||
lastKey = -1;
|
||||
}
|
||||
|
||||
// Now it's a new keypress - do a key down
|
||||
|
||||
if (c >= ' ' && c <= 127) {
|
||||
if (keymap[c-' '].shifted) {
|
||||
vmkeyboard->keyDepressed(LSHFT);
|
||||
}
|
||||
vmkeyboard->keyDepressed(keymap[c-' '].actualKey);
|
||||
|
||||
lastKey = c;
|
||||
return;
|
||||
}
|
||||
|
||||
// Any other key that could have been reported:
|
||||
// ESC RET TAB LA RA LARR RARR DARR UARR
|
||||
vmkeyboard->keyDepressed(c);
|
||||
|
||||
// anything else isn't reported by OpenCV, so we can't report it
|
||||
// specifically. So these are ignored:
|
||||
// _CTRL LSHFT RSHFT LOCK LA RA
|
||||
|
||||
lastKey = c;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#ifndef __OPENCV_KEYBOARD_H
|
||||
#define __OPENCV_KEYBOARD_H
|
||||
|
||||
#include "physicalkeyboard.h"
|
||||
#include "vmkeyboard.h"
|
||||
|
||||
class OpenCVKeyboard : public PhysicalKeyboard {
|
||||
public:
|
||||
OpenCVKeyboard(VMKeyboard *k);
|
||||
virtual ~OpenCVKeyboard();
|
||||
|
||||
virtual void maintainKeyboard();
|
||||
private:
|
||||
int lastKey;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,55 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "opencv-paddles.h"
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
// FIXME: abstract this somewhere
|
||||
#define WINDOWNAME "6502core"
|
||||
#define WINDOWHEIGHT (240*2)
|
||||
#define WINDOWWIDTH (320*2)
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
static void mouseCallback(int event, int x, int y, int flags, void* userdata)
|
||||
{
|
||||
OpenCVPaddles *a = (OpenCVPaddles *)userdata;
|
||||
|
||||
if (event == EVENT_MOUSEMOVE) {
|
||||
a->p0 = ((float) x / (float)WINDOWWIDTH) * 255.0;
|
||||
a->p1 = ((float) y / (float)WINDOWHEIGHT) * 255.0;
|
||||
}
|
||||
}
|
||||
|
||||
OpenCVPaddles::OpenCVPaddles()
|
||||
{
|
||||
p0 = p1 = 127;
|
||||
setMouseCallback(WINDOWNAME, mouseCallback, this);
|
||||
}
|
||||
|
||||
OpenCVPaddles::~OpenCVPaddles()
|
||||
{
|
||||
}
|
||||
|
||||
void OpenCVPaddles::startReading()
|
||||
{
|
||||
g_vm->triggerPaddleInCycles(0, 12 * p0);
|
||||
g_vm->triggerPaddleInCycles(1, 12 * p1);
|
||||
}
|
||||
|
||||
uint8_t OpenCVPaddles::paddle0()
|
||||
{
|
||||
return p0;
|
||||
}
|
||||
|
||||
uint8_t OpenCVPaddles::paddle1()
|
||||
{
|
||||
return p1;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "physicalpaddles.h"
|
||||
|
||||
class OpenCVPaddles : public PhysicalPaddles {
|
||||
public:
|
||||
OpenCVPaddles();
|
||||
virtual ~OpenCVPaddles();
|
||||
|
||||
virtual void startReading();
|
||||
virtual uint8_t paddle0();
|
||||
virtual uint8_t paddle1();
|
||||
|
||||
public:
|
||||
uint8_t p0;
|
||||
uint8_t p1;
|
||||
};
|
@ -1,75 +0,0 @@
|
||||
#include "opencv-printer.h"
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
#define WINDOWNAME "printer"
|
||||
|
||||
#define HEIGHT 800
|
||||
#define NATIVEWIDTH 960 // FIXME: printer can change density...
|
||||
|
||||
|
||||
//#define WIDTH 384 // emulating the teeny printer I've got
|
||||
#define WIDTH 960
|
||||
|
||||
OpenCVPrinter::OpenCVPrinter()
|
||||
{
|
||||
pixels = new Mat(HEIGHT, WIDTH, CV_8U);
|
||||
*pixels = cv::Scalar(0xFF);
|
||||
ypos = 0;
|
||||
isDirty = false;
|
||||
namedWindow(WINDOWNAME, CV_WINDOW_AUTOSIZE);
|
||||
}
|
||||
|
||||
OpenCVPrinter::~OpenCVPrinter()
|
||||
{
|
||||
delete pixels; pixels = NULL;
|
||||
}
|
||||
|
||||
void OpenCVPrinter::update()
|
||||
{
|
||||
if (isDirty) {
|
||||
imshow(WINDOWNAME, *pixels);
|
||||
isDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVPrinter::addLine(uint8_t *rowOfBits)
|
||||
{
|
||||
isDirty = true;
|
||||
for (int yoff=0; yoff<9; yoff++) {
|
||||
// 960 pixels == 120 bytes -- FIXME
|
||||
for (int i=0; i<(NATIVEWIDTH/8); i++) {
|
||||
uint8_t bv = rowOfBits[yoff*120+i];
|
||||
for (int xoff=0; xoff<8; xoff++) {
|
||||
// scale X from "actual FX80" coordinates to "real printer" coordinates
|
||||
uint16_t actualX = (uint16_t)(((float)(i*8+xoff) * (float)WIDTH) / (float)NATIVEWIDTH);
|
||||
|
||||
uint8_t oldPixel = pixels->at<uchar>((ypos + yoff)%HEIGHT, actualX);
|
||||
uint8_t pixelColor = (bv & (1 << (7-xoff))) ? 0x00 : 0xFF;
|
||||
// Make sure to preserve any pixels we've already drawn
|
||||
pixels->at<uchar>((ypos + yoff)%HEIGHT, actualX) = ~(~oldPixel | ~pixelColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ypos >= HEIGHT) {
|
||||
ypos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVPrinter::moveDownPixels(uint8_t p)
|
||||
{
|
||||
ypos+= p;
|
||||
if (ypos >= HEIGHT) {
|
||||
// clear page & restart
|
||||
*pixels = cv::Scalar(0xFF);
|
||||
ypos = 0;
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef __OPENCV_PRINTER_H
|
||||
#define __OPENCV_PRINTER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
#include "physicalprinter.h"
|
||||
|
||||
class OpenCVPrinter : public PhysicalPrinter {
|
||||
public:
|
||||
OpenCVPrinter();
|
||||
virtual ~OpenCVPrinter();
|
||||
|
||||
virtual void addLine(uint8_t *rowOfBits); // must be 960 pixels wide (120 bytes)
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void moveDownPixels(uint8_t p);
|
||||
|
||||
private:
|
||||
bool isDirty;
|
||||
uint16_t ypos;
|
||||
cv::Mat *pixels;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,143 +0,0 @@
|
||||
#include <time.h>
|
||||
#include <mach/mach_time.h>
|
||||
// Derived from
|
||||
// http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
|
||||
|
||||
#define ORWL_NANO (+1.0E-9)
|
||||
#define ORWL_GIGA UINT64_C(1000000000)
|
||||
#define NANOSECONDS_PER_SECOND 1000000000UL
|
||||
#define CYCLES_PER_SECOND 1023000UL
|
||||
#define NANOSECONDS_PER_CYCLE (NANOSECONDS_PER_SECOND / CYCLES_PER_SECOND)
|
||||
|
||||
static double orwl_timebase = 0.0;
|
||||
static uint64_t orwl_timestart = 0;
|
||||
static void _init_darwin_shim(void) {
|
||||
mach_timebase_info_data_t tb = { 0 };
|
||||
mach_timebase_info(&tb);
|
||||
orwl_timebase = tb.numer;
|
||||
orwl_timebase /= tb.denom;
|
||||
orwl_timestart = mach_absolute_time();
|
||||
}
|
||||
|
||||
static int do_gettime(struct timespec *tp) {
|
||||
double diff = (mach_absolute_time() - orwl_timestart) * orwl_timebase;
|
||||
tp->tv_sec = diff * ORWL_NANO;
|
||||
tp->tv_nsec = diff - (tp->tv_sec * ORWL_GIGA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// adds the number of microseconds that 'cycles' takes to *start and
|
||||
// returns it in *out
|
||||
static void timespec_add_cycles(struct timespec *start,
|
||||
uint32_t cycles,
|
||||
struct timespec *out)
|
||||
{
|
||||
out->tv_sec = start->tv_sec;
|
||||
out->tv_nsec = start->tv_nsec;
|
||||
|
||||
uint64_t nanosToAdd = NANOSECONDS_PER_CYCLE * cycles;
|
||||
out->tv_sec += (nanosToAdd / NANOSECONDS_PER_SECOND);
|
||||
out->tv_nsec += (nanosToAdd % NANOSECONDS_PER_SECOND);
|
||||
|
||||
if (out->tv_nsec >= 1000000000L) {
|
||||
out->tv_sec++ ;
|
||||
out->tv_nsec -= 1000000000L;
|
||||
}
|
||||
}
|
||||
|
||||
// adds the number of microseconds given to *start and
|
||||
// returns it in *out
|
||||
static void timespec_add_us(struct timespec *start,
|
||||
uint64_t micros,
|
||||
struct timespec *out)
|
||||
{
|
||||
out->tv_sec = start->tv_sec;
|
||||
out->tv_nsec = start->tv_nsec;
|
||||
|
||||
uint64_t nanosToAdd = micros * 1000L;
|
||||
out->tv_sec += (nanosToAdd / NANOSECONDS_PER_SECOND);
|
||||
out->tv_nsec += (nanosToAdd % NANOSECONDS_PER_SECOND);
|
||||
|
||||
if (out->tv_nsec >= 1000000000L) {
|
||||
out->tv_sec++ ;
|
||||
out->tv_nsec -= 1000000000L;
|
||||
}
|
||||
}
|
||||
|
||||
static void timespec_diff(struct timespec *start,
|
||||
struct timespec *end,
|
||||
struct timespec *diff,
|
||||
bool *negative) {
|
||||
struct timespec t;
|
||||
|
||||
if (negative)
|
||||
{
|
||||
*negative = false;
|
||||
}
|
||||
|
||||
// if start > end, swizzle...
|
||||
if ( (start->tv_sec > end->tv_sec) || ((start->tv_sec == end->tv_sec) && (start->tv_nsec > end->tv_nsec)) )
|
||||
{
|
||||
t=*start;
|
||||
*start=*end;
|
||||
*end=t;
|
||||
if (negative)
|
||||
{
|
||||
*negative = true;
|
||||
}
|
||||
}
|
||||
|
||||
// assuming time_t is signed ...
|
||||
if (end->tv_nsec < start->tv_nsec)
|
||||
{
|
||||
t.tv_sec = end->tv_sec - start->tv_sec - 1;
|
||||
t.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.tv_sec = end->tv_sec - start->tv_sec;
|
||||
t.tv_nsec = end->tv_nsec - start->tv_nsec;
|
||||
}
|
||||
|
||||
diff->tv_sec = t.tv_sec;
|
||||
diff->tv_nsec = t.tv_nsec;
|
||||
}
|
||||
|
||||
// tsCompare: return -1, 0, 1 for (a < b), (a == b), (a > b)
|
||||
static int8_t tsCompare(struct timespec *A, struct timespec *B)
|
||||
{
|
||||
if (A->tv_sec < B->tv_sec)
|
||||
return -1;
|
||||
|
||||
if (A->tv_sec > B->tv_sec)
|
||||
return 1;
|
||||
|
||||
if (A->tv_nsec < B->tv_nsec)
|
||||
return -1;
|
||||
|
||||
if (A->tv_nsec > B->tv_nsec)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct timespec tsSubtract(struct timespec time1, struct timespec time2)
|
||||
{
|
||||
struct timespec result;
|
||||
if ((time1.tv_sec < time2.tv_sec) ||
|
||||
((time1.tv_sec == time2.tv_sec) &&
|
||||
(time1.tv_nsec <= time2.tv_nsec))) {/* TIME1 <= TIME2? */
|
||||
result.tv_sec = result.tv_nsec = 0 ;
|
||||
} else {/* TIME1 > TIME2 */
|
||||
result.tv_sec = time1.tv_sec - time2.tv_sec ;
|
||||
if (time1.tv_nsec < time2.tv_nsec) {
|
||||
result.tv_nsec = time1.tv_nsec + 1000000000L - time2.tv_nsec ;
|
||||
result.tv_sec-- ;/* Borrow a second. */
|
||||
} else {
|
||||
result.tv_nsec = time1.tv_nsec - time2.tv_nsec ;
|
||||
}
|
||||
}
|
||||
|
||||
return (result) ;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user