Navigation Menu

Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/triddle/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
rcaputo committed Aug 5, 2012
2 parents 28ba6b5 + d7cfe37 commit f97cdcb
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 597 deletions.
488 changes: 0 additions & 488 deletions Firmdata-atmega328.hex

This file was deleted.

32 changes: 30 additions & 2 deletions README.md
Expand Up @@ -79,7 +79,35 @@ The following features remain to be implemented:
would be very good.
* Get faster, better, stronger IO channels running such as Ethernet.


INSTALL

Uploading to Arduino Uno on MacOSX
* avrdude -F -V -c arduino -p ATMEGA328P -P /dev/cu.usbmodem641 -b 115200 -U flash:w:Firmdata-atmega328p.hex

Uploading to Arduino Duemilanove on Windows
* avrdude -pm328p -cstk500v1 -Pcom3 -b57600 -Uflash:w:Firmdata-atmega328p.hex:a

COMPILE

The Firmware is built using the avr-gcc/avr-libc integration for Eclipse. To compile the software outside of Eclipse follow this guide:

Uploading to Arduino Uno on MacOSX:
Install the following required GNU tools as detailed at http://www.nongnu.org/avr-libc/user-manual/install_tools.html

* GNU Binutils
* GCC
* AVR LibC
* AVRDUDE

There should be a Makefile but there isn't right now so once all the tools are installed do something like this:

avrdude -F -V -c arduino -p ATMEGA328P -P /dev/cu.usbmodem641 -b 115200 -U flash:w:Firmdata-atmega328p.hex
avr-gcc -DF_CPU=16000000UL -mmcu=atmega328p -Wall -g2 -gstabs -Os \
-fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields \
-Wl,-Map,Firmdata-atmega328p.map -o "Firmdata-atmega328p.elf" *.c

avr-objcopy -j .text -j .data -O ihex Firmdata-atmega328p.elf Firmdata-atmega328p.hex

Then upload the Firmdata-atmega328p.elf file to the Arduino using the INSTALL instructions above.

24 changes: 14 additions & 10 deletions RPM.pm
Expand Up @@ -81,21 +81,23 @@ sub got_magnetometer {
$self->outside_pole($when);
$self->currentPole(undef);
}
} else {
if ($value > 135) {
$self->currentPole('s');
$self->inside_pole($when);

} elsif ($value < 122) {
$self->currentPole('n');
$self->inside_pole($when);
}
}

#a single reading may both indicate that a pole is no longer present
#and that a new one has been detected so this should not be in an else
#block with the logic above that clears out the current pole
if ($value > 135) {
$self->currentPole('s');
$self->inside_pole($when);
} elsif ($value < 122) {
$self->currentPole('n');
$self->inside_pole($when);
}
}

sub inside_pole {
my ($self, $when) = @_;

#this is where north poles could be counted
}

#counting a turn when a pole is left instead of when it is entered
Expand All @@ -119,6 +121,8 @@ sub outside_pole {

sub got_knob {
my ($self, $when, $value) = @_;

warn "Knob at $when";
}

return "RPMController";
17 changes: 16 additions & 1 deletion lib/Device/Firmdata.pm
Expand Up @@ -44,7 +44,7 @@ sub build_io {
if ($^O eq 'MSWin32') {
$ioRole = 'Device::Firmdata::Role::IO::Win32Serial';
} else {
$ioRole = 'Device::Firmdata::Role::IO::DeviceSerial';
$ioRole = 'Device::Firmdata::Role::IO::Serial';
}

unless(defined($portName)) {
Expand All @@ -58,6 +58,20 @@ sub build_io {
return $metaclass->new_object(portName => $portName);
}

sub build_session {
my ($self) = @_;
my $sessionFile = $self->config->{sessionFile};
my $sessionClass;

if (defined($sessionFile)) {
$sessionClass = require $sessionFile;
} else {
$sessionClass = 'Device::Firmdata::Session';
}

return $sessionClass->new(host => $self);
}

sub run {
my ($self) = @_;

Expand Down Expand Up @@ -178,6 +192,7 @@ sub handleSystemMessage_beacon {

$self->session(Device::Firmdata::Session->new(host => $self));

$self->session($self->build_session);
$self->session->sessionOpen;
}

Expand Down
6 changes: 4 additions & 2 deletions lib/Device/Firmdata/Role/IO.pm
Expand Up @@ -18,7 +18,7 @@ use constant HEADER_LENGTH => 1;

sub getHeader {
my ($self) = @_;
my $headerByte = $self->read(1);
my $headerByte = $self->read(HEADER_LENGTH);
my $headerValue = unpack('C', $headerByte);
my $channel = ($headerValue & HEADER_CHANNEL_MASK) >> HEADER_CHANNEL_SHIFT;
my $length = $headerValue & HEADER_SIZE_MASK;
Expand All @@ -29,9 +29,11 @@ sub getHeader {
sub getMessage {
my ($self) = @_;
my ($channel, $length) = $self->getHeader;
my $content = $self->read($length);
my $content = $self->read($length) if $length > 0;
my $bytesRead = $length + HEADER_LENGTH;

$content = '' unless defined $content;

$self->bytesRead->add($bytesRead);

return ($channel, $content, $bytesRead);
Expand Down
176 changes: 83 additions & 93 deletions lib/Device/Firmdata/Role/IO/DeviceSerial.pm
@@ -1,94 +1,84 @@
package Device::Firmdata::Role::IO::DeviceSerial;

use Moose::Role;
use Device::SerialPort;
use Symbol qw(gensym);

with 'Device::Firmdata::Role::IO';

has driver => ( is => 'ro', isa => 'Device::SerialPort', required => 1, builder => 'build_driver', lazy => 1 );

sub build_portName {
my ($self) = @_;

opendir my $dir, "/dev" or die $!;
my @modems = grep /^cu\.usbmodem/, readdir $dir;

die "Can't find a modem in /dev ...\n" if @modems < 1;
die "Don't know which modem to use: @modems\n" if @modems > 1;

return "/dev/$modems[0]";
}


sub build_driver {
my ($self) = @_;

my $driver = Device::SerialPort->new($self->portName());
$driver->debug(1);

#$driver->datatype("raw");
$driver->baudrate(57600) or die "Could not set baud: $^E";
$driver->databits(8);
$driver->parity('none') or die "Could not set parity: $^E";
$driver->stopbits(1) or die "Could not set stopbits: $^E";

$driver->stty_echo(0);

# Block indefinitely.
$driver->read_const_time(0);
$driver->read_char_time(0);

$driver->write_settings();

return $driver;
}

sub read {
my ($self, $bytes) = @_;

# Device::SerialPort is often returning short strings, and I'm not
# sure why. It was more expedient to work around that here.

my $done_buf = "";

my $done = 0;
while ($done < $bytes) {
my ($bytesRead, $buf) = $self->driver->read($bytes - $done);
die "Could not read: $!" if $bytesRead < 0;

if ($done + $bytesRead > $bytes) {
die "Device::SerialPort is a bastard ($done + $bytesRead > $bytes)";
}

$done_buf .= $buf;
$done += $bytesRead;
}

if (0) {
use bytes;
my $ascii = $done_buf;
$ascii =~ s/([^ -~])/sprintf '\x{%02x}', ord($1)/eg;
warn "<<< $done ($ascii)\n";
}

return $done_buf;
}

sub write {
my ($self, $content) = @_;

use bytes;
my $length = length($content);
my $written;

$written = $self->driver->write($content);

if ($written != $length) {
die "tried to write $length bytes but only wrote $written: $!";
}

return;
}

package Device::Firmdata::Role::IO::DeviceSerial;

use Moose::Role;
use Device::SerialPort;
use Symbol qw(gensym);

with 'Device::Firmdata::Role::IO';

has driver => ( is => 'ro', isa => 'Device::SerialPort', required => 1, builder => 'build_driver', lazy => 1 );

sub build_portName {
my ($self) = @_;

opendir my $dir, "/dev" or die $!;
my @modems = grep /^cu\.usbmodem/, readdir $dir;

die "Can't find a modem in /dev ...\n" if @modems < 1;
die "Don't know which modem to use: @modems\n" if @modems > 1;

return "/dev/$modems[0]";
}


sub build_driver {
my ($self) = @_;

my $driver = Device::SerialPort->new($self->portName());
$driver->debug(1);

#$driver->datatype("raw");
$driver->baudrate(57600) or die "Could not set baud: $^E";
$driver->databits(8);
$driver->parity('none') or die "Could not set parity: $^E";
$driver->stopbits(1) or die "Could not set stopbits: $^E";

$driver->stty_echo(0);

$driver->read_const_time(10000);
$driver->read_char_time(0);

$driver->write_settings();

return $driver;
}

sub read {
my ($self, $bytes) = @_;
my $buf;

while(1) {
my ($bytesRead);

($bytesRead, $buf) = $self->driver->read($bytes);

next if $bytesRead == 0;

if ($bytesRead != $bytes) {
die "Tried to read $bytes bytes but only got $bytesRead";
}

last;
}

return $buf;

}

sub write {
my ($self, $content) = @_;

use bytes;
my $length = length($content);
my $written;

$written = $self->driver->write($content);

if ($written != $length) {
die "tried to write $length bytes but only wrote $written: $!";
}

return;
}

1;
63 changes: 63 additions & 0 deletions lib/Device/Firmdata/Role/IO/Serial.pm
@@ -0,0 +1,63 @@
package Device::Firmdata::Role::IO::Serial;

use Moose::Role;

with 'Device::Firmdata::Role::IO';

has fh => ( is => 'ro', isa => 'GlobRef', required => 1, lazy => 1, builder => 'build_fh' );

sub build_fh {
my ($self) = @_;
my $path = $self->portName;
my $fh;

die "Could not open $path for read/write" unless open($fh, '+>', $path);

return $fh;
}

sub read {
my ($self, $wantBytes) = @_;
my $bytesLeft = $wantBytes;
my $readBytes = 0;
my $outputBuf;

while($bytesLeft > 0) {
my $readBuf;
my $bytesRead = sysread($self->fh, $readBuf, $bytesLeft);

if ($bytesRead == -1) {
die "Could not read from fh: $!";
}

$bytesLeft -= $bytesRead;

$outputBuf .= $readBuf;
}

if ($bytesLeft < 0) {
die "read too much data";
}

return $outputBuf;
}

sub write {
my ($self, $content) = @_;
my $length = length($content);
my $bytesLeft = length($content);

while($bytesLeft > 0) {
my $bytesSent = syswrite($self->fh, $content, $bytesLeft, $length - $bytesLeft);

if ($bytesSent == -1) {
die "could not write to fh: $!";
}

$bytesLeft -= $bytesSent;
}

return;
}

1;
2 changes: 1 addition & 1 deletion work.pl
Expand Up @@ -8,4 +8,4 @@

my $firmdata = Device::Firmdata->new(config => { @ARGV } );

$firmdata->run;
$firmdata->run;

0 comments on commit f97cdcb

Please sign in to comment.