Working serial connection.
Still need some work on displaying the right chars at the right place.
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "SerialApp.h"
|
#include "SerialApp.h"
|
||||||
|
|
||||||
#include "SerialWindow.h"
|
#include "SerialWindow.h"
|
||||||
@@ -15,7 +17,7 @@ SerialApp::SerialApp()
|
|||||||
{
|
{
|
||||||
fWindow = new SerialWindow();
|
fWindow = new SerialWindow();
|
||||||
|
|
||||||
serialLock = create_sem(0, "Serial port lock");
|
fSerialLock = create_sem(0, "Serial port lock");
|
||||||
thread_id id = spawn_thread(PollSerial, "Serial port poller",
|
thread_id id = spawn_thread(PollSerial, "Serial port poller",
|
||||||
B_LOW_PRIORITY, this);
|
B_LOW_PRIORITY, this);
|
||||||
resume_thread(id);
|
resume_thread(id);
|
||||||
@@ -36,15 +38,25 @@ void SerialApp::MessageReceived(BMessage* message)
|
|||||||
{
|
{
|
||||||
const char* portName;
|
const char* portName;
|
||||||
message->FindString("port name", &portName);
|
message->FindString("port name", &portName);
|
||||||
serialPort.Open(portName);
|
fSerialPort.Open(portName);
|
||||||
release_sem(serialLock);
|
release_sem(fSerialLock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kMsgDataRead:
|
case kMsgDataRead:
|
||||||
{
|
{
|
||||||
// TODO forward to the window
|
// forward the message to the window, which will display the
|
||||||
|
// incoming data
|
||||||
|
fWindow->PostMessage(message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kMsgDataWrite:
|
||||||
|
{
|
||||||
|
const char* bytes;
|
||||||
|
ssize_t size;
|
||||||
|
|
||||||
|
message->FindData("data", B_RAW_TYPE, &(const void*)bytes, &size);
|
||||||
|
fSerialPort.Write(bytes, size);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BApplication::MessageReceived(message);
|
BApplication::MessageReceived(message);
|
||||||
}
|
}
|
||||||
@@ -61,16 +73,15 @@ status_t SerialApp::PollSerial(void*)
|
|||||||
{
|
{
|
||||||
ssize_t bytesRead;
|
ssize_t bytesRead;
|
||||||
|
|
||||||
bytesRead = application->serialPort.Read(buffer, 256);
|
bytesRead = application->fSerialPort.Read(buffer, 256);
|
||||||
if (bytesRead == B_FILE_ERROR)
|
if (bytesRead == B_FILE_ERROR)
|
||||||
{
|
{
|
||||||
// Port is not open - wait for it and start over
|
// Port is not open - wait for it and start over
|
||||||
acquire_sem(application->serialLock);
|
acquire_sem(application->fSerialLock);
|
||||||
} else {
|
} else if (bytesRead > 0) {
|
||||||
// We read something, forward it to the app for handling
|
// We read something, forward it to the app for handling
|
||||||
BMessage* serialData = new BMessage(kMsgDataRead);
|
BMessage* serialData = new BMessage(kMsgDataRead);
|
||||||
// TODO bytesRead is not nul terminated. Use generic data rather
|
serialData->AddData("data", B_RAW_TYPE, buffer, bytesRead);
|
||||||
serialData->AddString("data", buffer);
|
|
||||||
be_app_messenger.SendMessage(serialData);
|
be_app_messenger.SendMessage(serialData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,17 +19,19 @@ class SerialApp: public BApplication
|
|||||||
void MessageReceived(BMessage* message);
|
void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BSerialPort serialPort;
|
BSerialPort fSerialPort;
|
||||||
static status_t PollSerial(void*);
|
sem_id fSerialLock;
|
||||||
|
|
||||||
sem_id serialLock;
|
|
||||||
SerialWindow* fWindow;
|
SerialWindow* fWindow;
|
||||||
|
|
||||||
|
static status_t PollSerial(void*);
|
||||||
|
|
||||||
static const char* kApplicationSignature;
|
static const char* kApplicationSignature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum messageConstants {
|
enum messageConstants {
|
||||||
kMsgOpenPort = 'open',
|
kMsgOpenPort = 'open',
|
||||||
kMsgDataRead = 'dare',
|
kMsgDataRead = 'dare',
|
||||||
|
kMsgDataWrite = 'dawr',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,21 +12,22 @@
|
|||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
#include <SerialPort.h>
|
#include <SerialPort.h>
|
||||||
|
|
||||||
|
#include "SerialApp.h"
|
||||||
#include "TermView.h"
|
#include "TermView.h"
|
||||||
|
|
||||||
|
|
||||||
SerialWindow::SerialWindow()
|
SerialWindow::SerialWindow()
|
||||||
:
|
:
|
||||||
BWindow(BRect(100, 100, 400, 400), SerialWindow::kWindowTitle,
|
BWindow(BRect(100, 100, 400, 400), SerialWindow::kWindowTitle,
|
||||||
B_DOCUMENT_WINDOW, B_QUIT_ON_WINDOW_CLOSE)
|
B_DOCUMENT_WINDOW, B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS)
|
||||||
{
|
{
|
||||||
SetLayout(new BGroupLayout(B_VERTICAL, 0.0f));
|
SetLayout(new BGroupLayout(B_VERTICAL, 0.0f));
|
||||||
|
|
||||||
BMenuBar* menuBar = new BMenuBar("menuBar");
|
BMenuBar* menuBar = new BMenuBar("menuBar");
|
||||||
TermView* termView = new TermView();
|
fTermView = new TermView();
|
||||||
|
|
||||||
AddChild(menuBar);
|
AddChild(menuBar);
|
||||||
AddChild(termView);
|
AddChild(fTermView);
|
||||||
|
|
||||||
BMenu* connectionMenu = new BMenu("Connections");
|
BMenu* connectionMenu = new BMenu("Connections");
|
||||||
BMenu* editMenu = new BMenu("Edit");
|
BMenu* editMenu = new BMenu("Edit");
|
||||||
@@ -48,7 +49,9 @@ SerialWindow::SerialWindow()
|
|||||||
char buffer[256];
|
char buffer[256];
|
||||||
serialPort.GetDeviceName(i, buffer, 256);
|
serialPort.GetDeviceName(i, buffer, 256);
|
||||||
|
|
||||||
BMenuItem* portItem = new BMenuItem(buffer, NULL);
|
BMessage* message = new BMessage(kMsgOpenPort);
|
||||||
|
message->AddString("port name", buffer);
|
||||||
|
BMenuItem* portItem = new BMenuItem(buffer, message);
|
||||||
|
|
||||||
connect->AddItem(portItem);
|
connect->AddItem(portItem);
|
||||||
}
|
}
|
||||||
@@ -115,4 +118,28 @@ SerialWindow::SerialWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SerialWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch(message->what)
|
||||||
|
{
|
||||||
|
case kMsgDataRead:
|
||||||
|
{
|
||||||
|
const char* bytes;
|
||||||
|
ssize_t length;
|
||||||
|
message->FindData("data", B_RAW_TYPE, &(const void*)bytes, &length);
|
||||||
|
fTermView->PushBytes(bytes, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMsgOpenPort:
|
||||||
|
{
|
||||||
|
// Forward message to application
|
||||||
|
be_app->PostMessage(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* SerialWindow::kWindowTitle = "SerialConnect";
|
const char* SerialWindow::kWindowTitle = "SerialConnect";
|
||||||
|
|||||||
@@ -7,11 +7,18 @@
|
|||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
class TermView;
|
||||||
|
|
||||||
|
|
||||||
class SerialWindow: public BWindow
|
class SerialWindow: public BWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SerialWindow::SerialWindow();
|
SerialWindow::SerialWindow();
|
||||||
|
|
||||||
|
void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TermView* fTermView;
|
||||||
|
|
||||||
static const char* kWindowTitle;
|
static const char* kWindowTitle;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,12 +10,19 @@
|
|||||||
|
|
||||||
#include <Layout.h>
|
#include <Layout.h>
|
||||||
|
|
||||||
|
#include "SerialApp.h"
|
||||||
|
|
||||||
|
|
||||||
TermView::TermView()
|
TermView::TermView()
|
||||||
:
|
:
|
||||||
BView("TermView", B_WILL_DRAW)
|
BView("TermView", B_WILL_DRAW)
|
||||||
{
|
{
|
||||||
|
font_height height;
|
||||||
|
GetFontHeight(&height);
|
||||||
|
fFontHeight = height.ascent + height.descent + height.leading;
|
||||||
|
fFontWidth = be_fixed_font->StringWidth("X");
|
||||||
fTerm = vterm_new(kDefaultWidth, kDefaultHeight);
|
fTerm = vterm_new(kDefaultWidth, kDefaultHeight);
|
||||||
|
|
||||||
vterm_parser_set_utf8(fTerm, 1);
|
vterm_parser_set_utf8(fTerm, 1);
|
||||||
|
|
||||||
fTermScreen = vterm_obtain_screen(fTerm);
|
fTermScreen = vterm_obtain_screen(fTerm);
|
||||||
@@ -23,14 +30,6 @@ TermView::TermView()
|
|||||||
vterm_screen_reset(fTermScreen, 1);
|
vterm_screen_reset(fTermScreen, 1);
|
||||||
|
|
||||||
SetFont(be_fixed_font);
|
SetFont(be_fixed_font);
|
||||||
|
|
||||||
font_height height;
|
|
||||||
GetFontHeight(&height);
|
|
||||||
fFontHeight = height.ascent + height.descent + height.leading;
|
|
||||||
fFontWidth = be_fixed_font->StringWidth("X");
|
|
||||||
|
|
||||||
// TEST
|
|
||||||
//vterm_push_bytes(fTerm,"Hello World!",11);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -40,6 +39,12 @@ TermView::~TermView()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TermView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
MakeFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TermView::Draw(BRect updateRect)
|
void TermView::Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
VTermRect updatedChars = PixelsToGlyphs(updateRect);
|
VTermRect updatedChars = PixelsToGlyphs(updateRect);
|
||||||
@@ -66,6 +71,29 @@ void TermView::Draw(BRect updateRect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TermView::GetPreferredSize(float* width, float* height)
|
||||||
|
{
|
||||||
|
if (width != NULL)
|
||||||
|
*width = kDefaultWidth * fFontWidth;
|
||||||
|
if (height != NULL)
|
||||||
|
*height = kDefaultHeight * fFontHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TermView::KeyDown(const char* bytes, int32 numBytes)
|
||||||
|
{
|
||||||
|
BMessage* keyEvent = new BMessage(kMsgDataWrite);
|
||||||
|
keyEvent->AddData("data", B_RAW_TYPE, bytes, numBytes);
|
||||||
|
be_app_messenger.SendMessage(keyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TermView::PushBytes(const char* bytes, size_t length)
|
||||||
|
{
|
||||||
|
vterm_push_bytes(fTerm, bytes, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VTermRect TermView::PixelsToGlyphs(BRect pixels) const
|
VTermRect TermView::PixelsToGlyphs(BRect pixels) const
|
||||||
{
|
{
|
||||||
pixels.OffsetBy(-kBorderSpacing, -kBorderSpacing);
|
pixels.OffsetBy(-kBorderSpacing, -kBorderSpacing);
|
||||||
@@ -76,12 +104,17 @@ VTermRect TermView::PixelsToGlyphs(BRect pixels) const
|
|||||||
rect.start_row = (int)floor(pixels.top / fFontHeight);
|
rect.start_row = (int)floor(pixels.top / fFontHeight);
|
||||||
rect.end_row = (int)ceil(pixels.bottom / fFontHeight);
|
rect.end_row = (int)ceil(pixels.bottom / fFontHeight);
|
||||||
|
|
||||||
#if 0
|
printf(
|
||||||
printf("pixels:\t%d\t%d\t%d\t%d\n"
|
"TOP %d ch < %f px\n"
|
||||||
"glyps:\t%d\t%d\t%d\t%d\n",
|
"BTM %d ch < %f px\n"
|
||||||
(int)pixels.top, (int)pixels.bottom, (int)pixels.left, (int)pixels.right,
|
"LFT %d ch < %f px\n"
|
||||||
rect.start_row, rect.end_row, rect.start_col, rect.end_col);
|
"RGH %d ch < %f px\n",
|
||||||
#endif
|
rect.start_row, pixels.top,
|
||||||
|
rect.end_row, pixels.bottom,
|
||||||
|
rect.start_col, pixels.left,
|
||||||
|
rect.end_col, pixels.right
|
||||||
|
);
|
||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +127,19 @@ BRect TermView::GlyphsToPixels(const VTermRect& glyphs) const
|
|||||||
rect.left = glyphs.start_col * fFontWidth;
|
rect.left = glyphs.start_col * fFontWidth;
|
||||||
rect.right = glyphs.end_col * fFontWidth;
|
rect.right = glyphs.end_col * fFontWidth;
|
||||||
|
|
||||||
|
rect.OffsetBy(kBorderSpacing, kBorderSpacing);
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"TOP %d ch > %f px (%f)\n"
|
||||||
|
"BTM %d ch > %f px\n"
|
||||||
|
"LFT %d ch > %f px (%f)\n"
|
||||||
|
"RGH %d ch > %f px\n",
|
||||||
|
glyphs.start_row, rect.top, fFontHeight,
|
||||||
|
glyphs.end_row, rect.bottom,
|
||||||
|
glyphs.start_col, rect.left, fFontWidth,
|
||||||
|
glyphs.end_col, rect.right
|
||||||
|
);
|
||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,8 +155,25 @@ BRect TermView::GlyphsToPixels(const int width, const int height) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TermView::Damage(VTermRect rect)
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
// Invalidate(GlyphsToPixels(rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
int TermView::Damage(VTermRect rect, void* user)
|
||||||
|
{
|
||||||
|
TermView* view = (TermView*)user;
|
||||||
|
view->Damage(rect);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const VTermScreenCallbacks TermView::sScreenCallbacks = {
|
const VTermScreenCallbacks TermView::sScreenCallbacks = {
|
||||||
/*.damage =*/ NULL,
|
&TermView::Damage,
|
||||||
/*.moverect =*/ NULL,
|
/*.moverect =*/ NULL,
|
||||||
/*.movecursor =*/ NULL,
|
/*.movecursor =*/ NULL,
|
||||||
/*.settermprop =*/ NULL,
|
/*.settermprop =*/ NULL,
|
||||||
|
|||||||
@@ -16,12 +16,19 @@ class TermView: public BView
|
|||||||
TermView();
|
TermView();
|
||||||
~TermView();
|
~TermView();
|
||||||
|
|
||||||
|
void AttachedToWindow();
|
||||||
void Draw(BRect updateRect);
|
void Draw(BRect updateRect);
|
||||||
|
void GetPreferredSize(float* width, float* height);
|
||||||
|
void KeyDown(const char* bytes, int32 numBytes);
|
||||||
|
void PushBytes(const char* bytes, const size_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VTermRect PixelsToGlyphs(BRect pixels) const;
|
VTermRect PixelsToGlyphs(BRect pixels) const;
|
||||||
BRect GlyphsToPixels(const VTermRect& glyphs) const;
|
BRect GlyphsToPixels(const VTermRect& glyphs) const;
|
||||||
BRect GlyphsToPixels(const int width, const int height) const;
|
BRect GlyphsToPixels(const int width, const int height) const;
|
||||||
|
void Damage(VTermRect rect);
|
||||||
|
|
||||||
|
static int Damage(VTermRect rect, void* user);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VTerm* fTerm;
|
VTerm* fTerm;
|
||||||
|
|||||||
Reference in New Issue
Block a user