Publication
parent
efce1c3756
commit
b54cdb0688
@ -0,0 +1,11 @@
|
|||||||
|
Copyright 2023 Aaron M. Schinder
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,9 @@
|
|||||||
|
Aaron M. Schinder
|
||||||
|
|
||||||
|
October 2023
|
||||||
|
|
||||||
|
Embedded software serial communications protocol
|
||||||
|
|
||||||
|
This is a way to have my various arduino-nano controlled embedded perhipherals talk to each other, and to the Raspberry pi using any 3 available GPIO ports. Sometimes I need more than one perhipheral to talk to a controller, and I run out of dedicated serial ports. This allows the use of any 3 GPIO pins on the controller and perhipheral to facilitate two-way non-blocking communications.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,238 @@
|
|||||||
|
#include "ams20x4LCD.hpp"
|
||||||
|
#include "amswirelib.hpp"
|
||||||
|
|
||||||
|
const static unsigned long rwdelay = 1000;
|
||||||
|
|
||||||
|
lcd20x4::lcd20x4()
|
||||||
|
{
|
||||||
|
int I;
|
||||||
|
pin_RS = 0;
|
||||||
|
pin_RW = 0;
|
||||||
|
pin_E = 0;
|
||||||
|
for(I=0;I<8;I++) pin_DB[I] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd20x4::~lcd20x4()
|
||||||
|
{
|
||||||
|
int I;
|
||||||
|
pin_RS = 0;
|
||||||
|
pin_RW = 0;
|
||||||
|
pin_E = 0;
|
||||||
|
for(I=0;I<8;I++) pin_DB[I] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::setup(uint8_t RSpin, uint8_t RWpin, uint8_t Epin, const uint8_t* DBpins)
|
||||||
|
{
|
||||||
|
int I;
|
||||||
|
pin_RS = RSpin;
|
||||||
|
pin_RW = RWpin;
|
||||||
|
pin_E = Epin;
|
||||||
|
set_pinmode(pin_RS,1);
|
||||||
|
set_pinmode(pin_RW,1);
|
||||||
|
set_pinmode(pin_E,1);
|
||||||
|
|
||||||
|
for(I=0;I<8;I++)
|
||||||
|
{
|
||||||
|
pin_DB[I] = DBpins[I];
|
||||||
|
set_pinmode(pin_DB[I],1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cursx = 0;
|
||||||
|
cursy = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::loop()
|
||||||
|
{
|
||||||
|
//nothing really
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lcd20x4::read_op(uint8_t b, uint8_t RS)
|
||||||
|
{
|
||||||
|
uint8_t ret = 0;
|
||||||
|
uint8_t bt = 0;
|
||||||
|
int I;
|
||||||
|
for(I=0;I<8;I++)
|
||||||
|
{
|
||||||
|
set_pinmode(pin_DB[I],0);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_pin(pin_E,1);
|
||||||
|
write_pin(pin_RW,1);
|
||||||
|
write_pin(pin_RS,RS);
|
||||||
|
delayMicroseconds(rwdelay);
|
||||||
|
|
||||||
|
for(I=0;I<8;I++)
|
||||||
|
{
|
||||||
|
bt = read_pin(pin_DB[I]);
|
||||||
|
ret = ret + bt<<I;
|
||||||
|
}
|
||||||
|
|
||||||
|
delayMicroseconds(rwdelay);
|
||||||
|
write_pin(pin_E,0);
|
||||||
|
|
||||||
|
for(I=0;I<8;I++)
|
||||||
|
{
|
||||||
|
set_pinmode(pin_DB[I],1);
|
||||||
|
}
|
||||||
|
delayMicroseconds(rwdelay);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void lcd20x4::write_op(uint8_t b, uint8_t RS)
|
||||||
|
{
|
||||||
|
int I;
|
||||||
|
|
||||||
|
write_pin(pin_E,1);
|
||||||
|
write_pin(pin_RW,0);
|
||||||
|
write_pin(pin_RS,RS);
|
||||||
|
delayMicroseconds(rwdelay);
|
||||||
|
|
||||||
|
for(I=0;I<8;I++)
|
||||||
|
{
|
||||||
|
write_pin(pin_DB[I],(b & (1<<I))>>I);
|
||||||
|
}
|
||||||
|
|
||||||
|
delayMicroseconds(rwdelay);
|
||||||
|
write_pin(pin_E,0);
|
||||||
|
delayMicroseconds(rwdelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::display_clear()
|
||||||
|
{
|
||||||
|
write_op(0b00000001,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::cursor_home()
|
||||||
|
{
|
||||||
|
write_op(0b00000010,0);
|
||||||
|
cursx = 0; cursy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::entrymode(bool ID, bool S)
|
||||||
|
{
|
||||||
|
write_op((1<<2) | (ID<<1) | S,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::display_toggle(bool display, bool cursor, bool charblink)
|
||||||
|
{
|
||||||
|
write_op((1<<3) | (display<<2) | (cursor<<1) | charblink, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::cursor_shift(bool screen_cursor, bool left_right)
|
||||||
|
{
|
||||||
|
write_op((1<<4) | (screen_cursor<<3) | (left_right<<2),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//void lcd20x4::function_set(uint8_t q)
|
||||||
|
//{
|
||||||
|
// write_op((1<<5) | (q & 0b00001111) , 0);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//DL: data length: 0 - 4-bit, 1 - 8-bit
|
||||||
|
//N: display lines: 0 - 1-line-mode 1 - 2-line-mode
|
||||||
|
//F: font: 0 - 5x8 1 - 5x10
|
||||||
|
void lcd20x4::function_set(bool DL,bool N,bool F)
|
||||||
|
{
|
||||||
|
write_op((1<<5)|(DL<<4)|(N<<3)|(F<<2),0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::CGRAM_set(uint8_t Acg_6bits)
|
||||||
|
{
|
||||||
|
write_op((1<<6)|(Acg_6bits & 0b00111111),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::DDRAM_set(uint8_t Add_7bits)
|
||||||
|
{
|
||||||
|
write_op((1<<7)|(Add_7bits & 0b01111111),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::setmydefs()
|
||||||
|
{
|
||||||
|
write_pin(pin_E,1);
|
||||||
|
delay(50);
|
||||||
|
write_op(0x30,0); //wake up 0x30 0b00110000
|
||||||
|
delay(50);
|
||||||
|
write_op(0x30,0); //wake up
|
||||||
|
delay(50);
|
||||||
|
write_op(0x30,0); //wake up
|
||||||
|
delay(50);
|
||||||
|
//write_op(0x38,0); //function set 8-bit, 2 lines 0b00111000
|
||||||
|
function_set(1,1,1);
|
||||||
|
delay(50);
|
||||||
|
//write_op(0x10,0); //set cursor? (looks like a function set to me?)
|
||||||
|
entrymode(1,0);
|
||||||
|
delay(50);
|
||||||
|
//write_op(0x0c,0); //0x0c 0b00001100
|
||||||
|
display_toggle(1,0,0);
|
||||||
|
//write_op(0x0c,0); //0x06 0b00000110
|
||||||
|
entrymode(1,0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// display_clear();
|
||||||
|
// cursor_home();
|
||||||
|
// entrymode(1,0);
|
||||||
|
// display_toggle(1,0,0);
|
||||||
|
// DDRAM_set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::set_pos(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
uint8_t b;
|
||||||
|
switch(y)
|
||||||
|
{
|
||||||
|
case 0: b = 0x00; break;
|
||||||
|
case 1: b = 0x40; break;
|
||||||
|
case 2: b = 0x14; break;
|
||||||
|
case 3: b = 0x54; break;
|
||||||
|
default: b = 0x00;
|
||||||
|
}
|
||||||
|
b += (x%20);
|
||||||
|
DDRAM_set(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::write_char(char b, uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
set_pos(x,y);
|
||||||
|
write_op((uint8_t) b, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::write_char(char b)
|
||||||
|
{
|
||||||
|
//may have to do translation of ASCII code
|
||||||
|
//01000001: A on the chart, 41h on ASCII chart - should be good
|
||||||
|
//write_op((uint8_t) b,1);
|
||||||
|
|
||||||
|
write_char(b,cursx,cursy);
|
||||||
|
cursx = cursx+1;
|
||||||
|
if(cursx>=20) {cursy = (cursy+1)%4; cursx = 0;}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::newline()
|
||||||
|
{
|
||||||
|
cursx = 0;
|
||||||
|
cursy = (cursy+1)%4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd20x4::write_chars(const char *bytes)
|
||||||
|
{
|
||||||
|
int I;
|
||||||
|
for(I=0;I<80;I++)
|
||||||
|
{
|
||||||
|
if(bytes[I]=='\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(bytes[I] == '\n')
|
||||||
|
{
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_char(bytes[I]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
#ifndef __AMS_20x4LCD_HPP__
|
||||||
|
#define __AMS_20x4LCD_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//https://electronicsforu.com/resources/learn-electronics/16x2-lcd-pinout-diagram
|
||||||
|
// Most LCDs contain Hitachi HD4478 controller.
|
||||||
|
// Arduino may already have a driver for this, but I need to learn
|
||||||
|
// to write my own drivers.
|
||||||
|
|
||||||
|
class lcd20x4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
lcd20x4();
|
||||||
|
~lcd20x4();
|
||||||
|
|
||||||
|
uint8_t cursx,cursy;
|
||||||
|
|
||||||
|
void setup(uint8_t RSpin, uint8_t RWpin, uint8_t Epin, const uint8_t* DBpins);
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
//11 pin control for 16-pin LCD screen
|
||||||
|
uint8_t pin_RS; //pin 4 register-select
|
||||||
|
//-0 instruction register (read), 1 data register (read/write)
|
||||||
|
uint8_t pin_RW; //pin 5 (read-write)
|
||||||
|
//-0 write, 1 read
|
||||||
|
uint8_t pin_E; //pin 6 enable
|
||||||
|
//high - enable read/write (clock for read/write?)
|
||||||
|
uint8_t pin_DB[8]; //pins 7-14 on LCD
|
||||||
|
//data bus
|
||||||
|
|
||||||
|
//blocking read/write operations
|
||||||
|
uint8_t read_op(uint8_t b, uint8_t RS);
|
||||||
|
void write_op(uint8_t b, uint8_t RS);
|
||||||
|
|
||||||
|
//control commands
|
||||||
|
void display_clear();
|
||||||
|
void cursor_home();
|
||||||
|
void entrymode(bool ID, bool S); //cursor advance direction and shift mode
|
||||||
|
//I/D - 1:increment/0:decrement S:1 display shift 0:cursor shift?
|
||||||
|
void display_toggle(bool display, bool cursor, bool charblink);
|
||||||
|
void cursor_shift(bool screen_cursor, bool left_right);
|
||||||
|
|
||||||
|
void CGRAM_set(uint8_t Acg_6bits); //sets CGRAM address - subsequent data is CG data
|
||||||
|
//user generated characters
|
||||||
|
void DDRAM_set(uint8_t Add_7bits); //sets DDRAM address - subsequent data is DD data
|
||||||
|
//00 - 4F (when display not shifted)
|
||||||
|
|
||||||
|
//DL: data length: 0 - 4-bit, 1 - 8-bit
|
||||||
|
//N: display lines: 0 - 1-line-mode 1 - 2-line-mode
|
||||||
|
//F: font: 0 - 5x8 1 - 5x10
|
||||||
|
void function_set(bool DL,bool N,bool F);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//D: display
|
||||||
|
//C: cursor
|
||||||
|
//B: blink
|
||||||
|
void displayonoff(bool D, bool C, bool B);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void setmydefs(); //sets reasonable screen defaults and clears screen
|
||||||
|
//writes a char and advances cursor
|
||||||
|
|
||||||
|
void set_pos(uint8_t x, uint8_t y);
|
||||||
|
void write_char(char b, uint8_t x, uint8_t y);
|
||||||
|
void write_char(char b);
|
||||||
|
//clears screen and writes a string (32 bytes max)
|
||||||
|
void write_chars(const char *bytes);
|
||||||
|
void newline();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,50 @@
|
|||||||
|
#include "amsgenlib.hpp"
|
||||||
|
|
||||||
|
utimer::utimer()
|
||||||
|
{
|
||||||
|
t = micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
utimer::~utimer()
|
||||||
|
{
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void utimer::set()
|
||||||
|
{
|
||||||
|
t = micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool utimer::isafter(unsigned long N)
|
||||||
|
{
|
||||||
|
bool ret = 0;
|
||||||
|
unsigned long t2,lmx;
|
||||||
|
if(t+N<t)
|
||||||
|
{
|
||||||
|
//wraparound
|
||||||
|
lmx = 0-1;
|
||||||
|
t2 = micros();
|
||||||
|
if(t2> ((t-lmx)+N))
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t2 = micros();
|
||||||
|
if(t2>t+N)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void utimer::delay(unsigned long N)
|
||||||
|
{
|
||||||
|
while(!this->isafter(N))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef __AMS_GENLIB_HPP__
|
||||||
|
#define __AMS_GENLIB_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
class utimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
utimer();
|
||||||
|
~utimer();
|
||||||
|
|
||||||
|
unsigned long t;
|
||||||
|
|
||||||
|
//sets the time in memory
|
||||||
|
void set();
|
||||||
|
|
||||||
|
//blocking delay
|
||||||
|
void delay(unsigned long N);
|
||||||
|
|
||||||
|
//is it N microseconds after the set time?
|
||||||
|
//solves wraparound at long overflow
|
||||||
|
bool isafter(unsigned long N);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,411 @@
|
|||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "amswirelib.hpp"
|
||||||
|
#include "amsgenlib.hpp"
|
||||||
|
|
||||||
|
#include "amsswcomm.hpp"
|
||||||
|
|
||||||
|
//initialize the sw communication channel
|
||||||
|
// each swcomm channel has 3 pins, the clock pin (controlled by the master),
|
||||||
|
// the input pin (receiving a signal from the other device)
|
||||||
|
// and an output pin (sending a signal to the other device)
|
||||||
|
//Inputs:
|
||||||
|
// ms - master or slave
|
||||||
|
// clkpin - the clock pin number
|
||||||
|
// outpin - the output pin number
|
||||||
|
// inpin - the input pin number
|
||||||
|
// divisor - how many updates to skip between clock changes
|
||||||
|
void amsswcomm::init(uint8_t _ms, uint8_t _clkpin, uint8_t _sendpin, uint8_t _recvpin, int _divisor)
|
||||||
|
{
|
||||||
|
|
||||||
|
ms = _ms;
|
||||||
|
clkpin = _clkpin;
|
||||||
|
sendpin = _sendpin;
|
||||||
|
recvpin = _recvpin;
|
||||||
|
|
||||||
|
|
||||||
|
divisor = _divisor;
|
||||||
|
clockticks = 0;
|
||||||
|
clockstate = 0;
|
||||||
|
lastclockstate = 0;
|
||||||
|
|
||||||
|
if(ms==1)
|
||||||
|
{
|
||||||
|
//master
|
||||||
|
set_pinmode(clkpin,1);
|
||||||
|
set_pinmode(recvpin,0);
|
||||||
|
set_pinmode(sendpin,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(ms==0)
|
||||||
|
{
|
||||||
|
//slave
|
||||||
|
set_pinmode(clkpin,0);
|
||||||
|
set_pinmode(recvpin,0);
|
||||||
|
set_pinmode(sendpin,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
clearrecvqueue();
|
||||||
|
clearsendqueue();
|
||||||
|
|
||||||
|
// recvmessage_size = -1;
|
||||||
|
// sendmessage_size = -1; //no message
|
||||||
|
// recvmessage_bit = 0;
|
||||||
|
// sendmessage_bit = 0;
|
||||||
|
|
||||||
|
// sendstate = 0;
|
||||||
|
// recvstate = 0;
|
||||||
|
// sendbytepointer = 0;
|
||||||
|
// recvbytepointer = 0;
|
||||||
|
// sendbitpointer = 0;
|
||||||
|
// recvbitpointer = 0;
|
||||||
|
|
||||||
|
int8_t I;
|
||||||
|
for(I=0;I<AMSSWCOMM_BUFFSIZE;I++)
|
||||||
|
{
|
||||||
|
sendmessage[I] = 0;
|
||||||
|
recvmessage[I] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amsswcomm::clearrecvqueue()
|
||||||
|
{
|
||||||
|
int8_t I;
|
||||||
|
|
||||||
|
recvmessage_size = -1;
|
||||||
|
recvmessage_byte = 0;
|
||||||
|
recvstate = 0;
|
||||||
|
recvbytepointer = 0;
|
||||||
|
recvbitpointer = 0;
|
||||||
|
|
||||||
|
// for speed, deal with this by sendmessage_size
|
||||||
|
// for(I=0;I<AMSSWCOMM_BUFFSIZE;I++)
|
||||||
|
// {
|
||||||
|
// recvmessage[I] = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amsswcomm::clearsendqueue()
|
||||||
|
{
|
||||||
|
int8_t I;
|
||||||
|
|
||||||
|
sendmessage_size = -1;
|
||||||
|
sendmessage_byte = 0;
|
||||||
|
sendstate = 0;
|
||||||
|
sendbytepointer = 0;
|
||||||
|
sendbitpointer = 0;
|
||||||
|
|
||||||
|
// for speed, deal with this by recvmessage_size
|
||||||
|
// for(I=0;I<AMSSWCOMM_BUFFSIZE;I++)
|
||||||
|
// {
|
||||||
|
// sendmessage[I] = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amsswcomm::update_step()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(ms==1)
|
||||||
|
{
|
||||||
|
//if master
|
||||||
|
|
||||||
|
if(clockticks<divisor)
|
||||||
|
{
|
||||||
|
clockticks++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clockticks = 0;
|
||||||
|
|
||||||
|
lastclockstate = clockstate;
|
||||||
|
clockstate = !lastclockstate;
|
||||||
|
write_pin(clkpin,clockstate);
|
||||||
|
|
||||||
|
//update_send triggers on rising edge of clkpin
|
||||||
|
if(clockstate==1 && lastclockstate==0)
|
||||||
|
{
|
||||||
|
update_send();
|
||||||
|
}
|
||||||
|
//update recv triggers on falling edge of clkpin
|
||||||
|
if(clockstate==0 && lastclockstate==1)
|
||||||
|
{
|
||||||
|
update_recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(ms==0)
|
||||||
|
{
|
||||||
|
//if servant
|
||||||
|
|
||||||
|
//check clock every passthrough
|
||||||
|
|
||||||
|
lastclockstate = clockstate;
|
||||||
|
clockstate = read_pin(clkpin);
|
||||||
|
|
||||||
|
//update_send triggers on rising edge of clkpin
|
||||||
|
if(clockstate==1 && lastclockstate==1)
|
||||||
|
{
|
||||||
|
update_send();
|
||||||
|
}
|
||||||
|
//update recv triggers on falling edge of clkpin
|
||||||
|
if(clockstate==0 && lastclockstate==1)
|
||||||
|
{
|
||||||
|
update_recv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//called by update_step
|
||||||
|
void amsswcomm::update_send()
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t bit;
|
||||||
|
|
||||||
|
if(sendstate==0)
|
||||||
|
{
|
||||||
|
//do nothing, no message
|
||||||
|
write_pin(sendpin,0); //send zeroes until messaging
|
||||||
|
}
|
||||||
|
else if(sendstate==1)
|
||||||
|
{
|
||||||
|
//send starting byte
|
||||||
|
sendmessage_byte = 0b0000001111111111;
|
||||||
|
|
||||||
|
bit = (sendmessage_byte & 1<<(9-sendbitpointer)) >> (9-sendbitpointer);
|
||||||
|
write_pin(sendpin,bit);
|
||||||
|
|
||||||
|
sendbitpointer++; //advance pointer
|
||||||
|
if(sendbitpointer>=10)
|
||||||
|
{
|
||||||
|
//if finished, advance state
|
||||||
|
sendbitpointer=0;
|
||||||
|
sendbytepointer=0;
|
||||||
|
sendstate=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(sendstate==2)
|
||||||
|
{
|
||||||
|
if(sendmessage_size>=0 && sendbytepointer<sendmessage_size)
|
||||||
|
{
|
||||||
|
sendmessage_byte = 0b0000001100000000 + sendmessage[sendbytepointer];
|
||||||
|
|
||||||
|
bit = (sendmessage_byte & 1<<(9-sendbitpointer)) >> (9-sendbitpointer);
|
||||||
|
write_pin(sendpin,bit);
|
||||||
|
|
||||||
|
sendbitpointer++; //advance pointer
|
||||||
|
if(sendbitpointer>=10)
|
||||||
|
{
|
||||||
|
//if finished, advance bytepointer
|
||||||
|
sendbitpointer=0;
|
||||||
|
sendbytepointer++;
|
||||||
|
}
|
||||||
|
if(sendbytepointer>sendmessage_size)
|
||||||
|
{
|
||||||
|
//if finished with message, advance state to send ending byte
|
||||||
|
sendbitpointer=0;
|
||||||
|
sendbytepointer=0;
|
||||||
|
sendstate=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//size 0 message
|
||||||
|
sendbitpointer=0;
|
||||||
|
sendbytepointer=0;
|
||||||
|
sendstate=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(sendstate==3)
|
||||||
|
{
|
||||||
|
//send ending byte
|
||||||
|
sendmessage_byte = 0; //if zero is received for more than 10 bits, end message
|
||||||
|
|
||||||
|
bit = (sendmessage_byte & 1<<(9-sendbitpointer)) >> (9-sendbitpointer);
|
||||||
|
write_pin(sendpin,bit);
|
||||||
|
|
||||||
|
sendbitpointer++; //advance pointer
|
||||||
|
if(sendbitpointer>=10)
|
||||||
|
{
|
||||||
|
//if finished, advance state
|
||||||
|
sendbitpointer=0;
|
||||||
|
sendbytepointer=0;
|
||||||
|
sendstate=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(sendstate==4)
|
||||||
|
{
|
||||||
|
clearsendqueue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//this shouldn't happen, but if it does, reset things
|
||||||
|
clearsendqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amsswcomm::update_recv()
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
|
||||||
|
if(recvstate==0)
|
||||||
|
{
|
||||||
|
bit = read_pin(recvpin);
|
||||||
|
if(bit==1)
|
||||||
|
{
|
||||||
|
recvstate=1; //advance to receive state
|
||||||
|
recvbitpointer=1;
|
||||||
|
recvmessage_byte = 0b0000001000000000; //set first leading bit
|
||||||
|
recvbytepointer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(recvstate==1)
|
||||||
|
{
|
||||||
|
bit = read_pin(recvpin);
|
||||||
|
recvmessage_byte = recvmessage_byte + (bit<<(9-recvbitpointer));
|
||||||
|
recvbitpointer++;
|
||||||
|
|
||||||
|
if(recvbitpointer>=10)
|
||||||
|
{
|
||||||
|
recvbitpointer = 0;
|
||||||
|
if(recvmessage_byte = 0b0000001111111111)
|
||||||
|
{
|
||||||
|
recvstate = 2;
|
||||||
|
recvmessage_byte = 0;
|
||||||
|
recvbytepointer = 0;
|
||||||
|
recvmessage_size = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//byte received not part of message or garbled message, ignore
|
||||||
|
recvstate = 0;
|
||||||
|
recvbytepointer = 0;
|
||||||
|
clearrecvqueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(recvstate==2)
|
||||||
|
{
|
||||||
|
bit = read_pin(recvpin);
|
||||||
|
recvmessage_byte = recvmessage_byte + (bit<<(9-recvbitpointer));
|
||||||
|
recvbitpointer++;
|
||||||
|
|
||||||
|
if(recvbitpointer>=10)
|
||||||
|
{
|
||||||
|
if(recvmessage_byte==0)
|
||||||
|
{
|
||||||
|
//end of message byte has been received
|
||||||
|
recvbitpointer = 0;
|
||||||
|
recvbytepointer = 0;
|
||||||
|
recvstate = 3; //has message
|
||||||
|
recvmessage_byte = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recvbitpointer = 0;
|
||||||
|
recvmessage[recvbytepointer] = (uint8_t)(recvmessage_byte & 0b0000000011111111);
|
||||||
|
recvbytepointer++;
|
||||||
|
recvmessage_size++;
|
||||||
|
recvmessage_byte = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(recvstate==3)
|
||||||
|
{
|
||||||
|
//has message, do nothing and wait until message has been processed
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clearrecvqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amsswcomm::has_message()
|
||||||
|
{
|
||||||
|
if(recvstate==3)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//receives the message and resets the receive queue
|
||||||
|
//return value is message size, or -1 for no message
|
||||||
|
int amsswcomm::recv_message(char *outputbuff, int outputbuffsize)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
int I;
|
||||||
|
|
||||||
|
if(has_message())
|
||||||
|
{
|
||||||
|
ret = recvmessage_size;
|
||||||
|
for(I=0;I<recvmessage_size && I<outputbuffsize && I<AMSSWCOMM_BUFFSIZE; I++)
|
||||||
|
{
|
||||||
|
outputbuff[I] = recvmessage[I];
|
||||||
|
}
|
||||||
|
if(I<outputbuffsize) outputbuff[I] = 0; //NULL terminate if possible to help string logic
|
||||||
|
|
||||||
|
for(I=0;I<AMSSWCOMM_BUFFSIZE;I++)
|
||||||
|
{
|
||||||
|
recvmessage[I] = 0;
|
||||||
|
}
|
||||||
|
recvmessage_size = -1;
|
||||||
|
// recvmessage_byte = 0;
|
||||||
|
// recvstate = 0;
|
||||||
|
// recvbytepointer = 0;
|
||||||
|
// recvbitpointer = 0;
|
||||||
|
clearrecvqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//places a message in the send queue
|
||||||
|
//1 - success
|
||||||
|
//0 - failure - a message is being sent, must wait to send
|
||||||
|
bool amsswcomm::send_message(char *inputbuff, int messagesize)
|
||||||
|
{
|
||||||
|
bool ret = 0;
|
||||||
|
int I;
|
||||||
|
|
||||||
|
if(sendstate==0)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
if(messagesize<=AMSSWCOMM_BUFFSIZE) sendmessage_size = messagesize; else sendmessage_size = AMSSWCOMM_BUFFSIZE;
|
||||||
|
for(I=0;I<sendmessage_size;I++)
|
||||||
|
{
|
||||||
|
sendmessage[I] = inputbuff[I];
|
||||||
|
}
|
||||||
|
for(I=sendmessage_size;I<AMSSWCOMM_BUFFSIZE;I++)
|
||||||
|
{
|
||||||
|
sendmessage[I] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendstate = 1; //start sending message
|
||||||
|
sendmessage_byte = 0;
|
||||||
|
sendbitpointer = 0;
|
||||||
|
sendbytepointer = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
#ifndef __AMSSWCOMM_HPP__
|
||||||
|
#define __AMSSWCOMM_HPP__
|
||||||
|
|
||||||
|
#define AMSSWCOMM_BUFFSIZE 64
|
||||||
|
//the size of the message buffer
|
||||||
|
|
||||||
|
class amsswcomm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
uint8_t ms;
|
||||||
|
uint8_t clkpin;
|
||||||
|
uint8_t sendpin;
|
||||||
|
uint8_t recvpin;
|
||||||
|
|
||||||
|
//time
|
||||||
|
int8_t divisor;
|
||||||
|
int8_t clockticks;
|
||||||
|
uint8_t lastclockstate;
|
||||||
|
uint8_t clockstate;
|
||||||
|
|
||||||
|
|
||||||
|
int16_t recvmessage_size;
|
||||||
|
uint16_t recvmessage_byte; //extended bit that is being received
|
||||||
|
int8_t recvstate;
|
||||||
|
//0 - no starting bit has been received
|
||||||
|
//1 - receive message start byte
|
||||||
|
//2 - receiving message bytes
|
||||||
|
//3 - message received - read and/or clear
|
||||||
|
int16_t recvbytepointer; //0 - 10, pointer to bit being received
|
||||||
|
uint8_t recvbitpointer; //pointer to byte being received
|
||||||
|
|
||||||
|
int16_t sendmessage_size;
|
||||||
|
uint16_t sendmessage_byte; //extended byte that is being sent
|
||||||
|
int8_t sendstate;
|
||||||
|
//0 - no message being sent
|
||||||
|
//1 - message exists in queue, send start byte
|
||||||
|
//2 - message exists in queue, send message bytes
|
||||||
|
//3 - send end message byte
|
||||||
|
//4 - clear message and reset
|
||||||
|
int16_t sendbytepointer; //0 - 10, pointer to byte being sent
|
||||||
|
uint8_t sendbitpointer; //pointer to byte being sent
|
||||||
|
|
||||||
|
|
||||||
|
char sendmessage[AMSSWCOMM_BUFFSIZE];
|
||||||
|
char recvmessage[AMSSWCOMM_BUFFSIZE];
|
||||||
|
|
||||||
|
|
||||||
|
//initialize the sw communication channel
|
||||||
|
// each swcomm channel has 3 pins, the clock pin (controlled by the master),
|
||||||
|
// the input pin (receiving a signal from the other device)
|
||||||
|
// and an output pin (sending a signal to the other device)
|
||||||
|
//Inputs:
|
||||||
|
// ms - master or slave
|
||||||
|
// clkpin - the clock pin number
|
||||||
|
// outpin - the output pin number
|
||||||
|
// inpin - the input pin number
|
||||||
|
void init(uint8_t _ms, uint8_t _clkpin, uint8_t _sendpin, uint8_t _recvpin, int _divisor);
|
||||||
|
|
||||||
|
//called on each timestep to update the state of the communicator
|
||||||
|
void update_step();
|
||||||
|
|
||||||
|
//called by update_step
|
||||||
|
void update_send();
|
||||||
|
void update_recv();
|
||||||
|
|
||||||
|
//communicator has received a complete message
|
||||||
|
//int is the size of the message, or -1 for no message received
|
||||||
|
bool has_message();
|
||||||
|
|
||||||
|
//receives the message and resets the receive queue
|
||||||
|
//return value is message size, or -1 for no message
|
||||||
|
int recv_message(char *outputbuff, int outputbuffsize);
|
||||||
|
|
||||||
|
//clears a received message and prepares to receive again
|
||||||
|
void clearrecvqueue();
|
||||||
|
void clearsendqueue();
|
||||||
|
|
||||||
|
//places a message in the send queue
|
||||||
|
//1 - success
|
||||||
|
//0 - failure - a message is being sent, must wait to send
|
||||||
|
bool send_message(char *inputbuff, int messagesize);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,172 @@
|
|||||||
|
#include "amswirelib.hpp"
|
||||||
|
|
||||||
|
uint8_t read_portsD()
|
||||||
|
{
|
||||||
|
return PIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_portsB()
|
||||||
|
{
|
||||||
|
return PINB;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_portsC()
|
||||||
|
{
|
||||||
|
return PINC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_portD(uint8_t N)
|
||||||
|
{
|
||||||
|
return (PIND & (1<<N))>>N;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_portB(uint8_t N)
|
||||||
|
{
|
||||||
|
return (PINB & (1<<N))>>N;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_portC(uint8_t N)
|
||||||
|
{
|
||||||
|
return (PINC & (1<<N))>>N;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_portsD(uint8_t V)
|
||||||
|
{
|
||||||
|
PORTD = V;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_portsB(uint8_t V)
|
||||||
|
{
|
||||||
|
PORTB = V;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_portsC(uint8_t V)
|
||||||
|
{
|
||||||
|
PORTC = V;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_portD(uint8_t N, uint8_t V)
|
||||||
|
{
|
||||||
|
PORTD = (PORTD & ~(1<<N)) | ((V & 0x01)<<N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_portB(uint8_t N, uint8_t V)
|
||||||
|
{
|
||||||
|
PORTB = (PORTB & ~(1<<N)) | ((V & 0x01)<<N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_portC(uint8_t N, uint8_t V)
|
||||||
|
{
|
||||||
|
PORTC = (PORTC & ~(1<<N)) | ((V & 0x01)<<N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_portsmodeD(uint8_t iomode)
|
||||||
|
{
|
||||||
|
DDRD = iomode;
|
||||||
|
}
|
||||||
|
void set_portsmodeB(uint8_t iomode)
|
||||||
|
{
|
||||||
|
DDRB = iomode;
|
||||||
|
}
|
||||||
|
void set_portsmodeC(uint8_t iomode)
|
||||||
|
{
|
||||||
|
DDRC = iomode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_portmodeD(uint8_t N, uint8_t iomode)
|
||||||
|
{
|
||||||
|
DDRD = (DDRD & ~(1<<N)) | ((iomode & 0x01)<<N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_portmodeB(uint8_t N, uint8_t iomode)
|
||||||
|
{
|
||||||
|
DDRB = (DDRB & ~(1<<N)) | ((iomode & 0x01)<<N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_portmodeC(uint8_t N, uint8_t iomode)
|
||||||
|
{
|
||||||
|
DDRC = (DDRC & ~(1<<N)) | ((iomode & 0x01)<<N);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Numbered Pin Digital IO
|
||||||
|
//amsPN mapping for Arduino Nano
|
||||||
|
//0-7 - PORTD
|
||||||
|
//8-15 - PORTB
|
||||||
|
//16-23 - PORTC (Analog Pins)
|
||||||
|
|
||||||
|
//1 - output, 0 - input
|
||||||
|
void set_pinmode(uint8_t amsPN, uint8_t iomode)
|
||||||
|
{
|
||||||
|
uint8_t N;
|
||||||
|
if(amsPN>=0&&amsPN<=7)
|
||||||
|
{
|
||||||
|
N = amsPN-0;
|
||||||
|
DDRD = (DDRD & ~(1<<N)) | ((iomode & 0x01)<<N);
|
||||||
|
}
|
||||||
|
else if(amsPN>=8 && amsPN<=15)
|
||||||
|
{
|
||||||
|
N = amsPN-8;
|
||||||
|
DDRB = (DDRB & ~(1<<N)) | ((iomode & 0x01)<<N);
|
||||||
|
}
|
||||||
|
else if(amsPN>=16&&amsPN<=23)
|
||||||
|
{
|
||||||
|
N = amsPN-16;
|
||||||
|
DDRC = (DDRC & ~(1<<N)) | ((iomode & 0x01)<<N);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//nothing;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_pin(uint8_t amsPN, uint8_t V)
|
||||||
|
{
|
||||||
|
uint8_t N;
|
||||||
|
if(amsPN>=0&&amsPN<=7)
|
||||||
|
{
|
||||||
|
N = amsPN-0;
|
||||||
|
PORTD = (PORTD & ~(1<<N)) | ((V & 0x01)<<N);
|
||||||
|
}
|
||||||
|
else if(amsPN>=8 && amsPN<=15)
|
||||||
|
{
|
||||||
|
N = amsPN-8;
|
||||||
|
PORTB = (PORTB & ~(1<<N)) | ((V & 0x01)<<N);
|
||||||
|
}
|
||||||
|
else if(amsPN>=16&&amsPN<=23)
|
||||||
|
{
|
||||||
|
N = amsPN-16;
|
||||||
|
PORTC = (PORTC & ~(1<<N)) | ((V & 0x01)<<N);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//nothing;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_pin(uint8_t amsPN)
|
||||||
|
{
|
||||||
|
uint8_t ret = 0;
|
||||||
|
uint8_t N;
|
||||||
|
if(amsPN>=0&&amsPN<=7)
|
||||||
|
{
|
||||||
|
N = amsPN-0;
|
||||||
|
ret = (PIND & (1<<N))>>N;
|
||||||
|
}
|
||||||
|
else if(amsPN>=8 && amsPN<=15)
|
||||||
|
{
|
||||||
|
N = amsPN-8;
|
||||||
|
ret = (PINB & (1<<N))>>N;
|
||||||
|
}
|
||||||
|
else if(amsPN>=16&&amsPN<=23)
|
||||||
|
{
|
||||||
|
N = amsPN-16;
|
||||||
|
ret = (PINC & (1<<N))>>N;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//nothing;
|
||||||
|
}
|
||||||
|
return ret;;
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef __AMS_WIRELIB_HPP__
|
||||||
|
#define __AMS_WIRELIB_HPP__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//Routines for fast digital read/write from the PORTs, PINs, DDRs
|
||||||
|
//This is specific to Arduino Nano
|
||||||
|
|
||||||
|
uint8_t read_portsD();
|
||||||
|
uint8_t read_portsB();
|
||||||
|
uint8_t read_portsC();
|
||||||
|
|
||||||
|
uint8_t read_portD(uint8_t N);
|
||||||
|
uint8_t read_portB(uint8_t N);
|
||||||
|
uint8_t read_portC(uint8_t N);
|
||||||
|
|
||||||
|
void write_portsD(uint8_t V);
|
||||||
|
void write_portsB(uint8_t V);
|
||||||
|
void write_portsC(uint8_t V);
|
||||||
|
|
||||||
|
void write_portD(uint8_t N, uint8_t V);
|
||||||
|
void write_portB(uint8_t N, uint8_t V);
|
||||||
|
void write_portC(uint8_t N, uint8_t V);
|
||||||
|
|
||||||
|
void set_portsmodeD(uint8_t iomode);
|
||||||
|
void set_portsmodeB(uint8_t iomode);
|
||||||
|
void set_portsmodeC(uint8_t iomode);
|
||||||
|
|
||||||
|
void set_portmodeD(uint8_t N, uint8_t iomode);
|
||||||
|
void set_portmodeB(uint8_t N, uint8_t iomode);
|
||||||
|
void set_portmodeC(uint8_t N, uint8_t iomode);
|
||||||
|
|
||||||
|
//Numbered Pin Digital IO
|
||||||
|
//amsPN mapping for Arduino Nano
|
||||||
|
//0-7 - PORTD
|
||||||
|
//8-15 - PORTB
|
||||||
|
//16-23 - PORTC (Analog Pins)
|
||||||
|
|
||||||
|
//1 - output, 0 - input
|
||||||
|
void set_pinmode(uint8_t amsPN, uint8_t iomode);
|
||||||
|
uint8_t read_pin(uint8_t amsPN);
|
||||||
|
void write_pin(uint8_t amsPN, uint8_t V);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,69 @@
|
|||||||
|
//#include "ams_swserial.hpp"
|
||||||
|
#include "amswirelib.hpp"
|
||||||
|
#include "amsgenlib.hpp"
|
||||||
|
#include "ams20x4LCD.hpp"
|
||||||
|
|
||||||
|
#include "amsswcomm.hpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
lcd20x4 lcd;
|
||||||
|
amsswcomm comm;
|
||||||
|
|
||||||
|
char buff1[128];
|
||||||
|
|
||||||
|
unsigned long loopcount;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
const uint8_t q[8] = {9,10,21,20,19,18,17,16};
|
||||||
|
lcd.setup(6,7,8,q);
|
||||||
|
lcd.setmydefs();
|
||||||
|
//initialize
|
||||||
|
lcd.display_clear();
|
||||||
|
lcd.cursor_home();
|
||||||
|
lcd.write_chars("INIT");
|
||||||
|
//set up comm as a servant receiver
|
||||||
|
//C1 - D2 - pin 2 - using as CLK
|
||||||
|
//C2 - D3 - pin 3 - using as sendpin
|
||||||
|
//C3 - D4 - pin 4 - using as recvpin
|
||||||
|
//C4 - D5 - pin 5
|
||||||
|
// divisor = 5 ticks
|
||||||
|
comm.init(0,2,3,4,5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
comm.update_step();
|
||||||
|
if(comm.has_message())
|
||||||
|
{
|
||||||
|
comm.recv_message(buff1,128);
|
||||||
|
buff1[127] = 0;
|
||||||
|
comm.send_message("ACK",4);
|
||||||
|
lcd.display_clear();
|
||||||
|
lcd.cursor_home();
|
||||||
|
lcd.write_chars(buff1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//void setup()
|
||||||
|
//{
|
||||||
|
// set_pinmode(2,1);
|
||||||
|
// set_pinmode(3,1);
|
||||||
|
// set_pinmode(4,1);
|
||||||
|
// loopcount = 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// Test pins
|
||||||
|
//void loop()
|
||||||
|
//{
|
||||||
|
// delay(100);
|
||||||
|
// write_pin(2, loopcount%2);
|
||||||
|
// write_pin(3, (loopcount/2)%2);
|
||||||
|
// write_pin(4, (loopcount/4)%2);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// loopcount = loopcount + 1;
|
||||||
|
// loopcount = loopcount % 16;
|
||||||
|
//}
|
@ -0,0 +1,303 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os,sys,math
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
#whatever arduino GPIO library
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## dummy functions for now - work through the logic while you still have it in your head!
|
||||||
|
def set_pinmode(pinnumber, mode):
|
||||||
|
|
||||||
|
#set GPIO mode to BOARD
|
||||||
|
if(mode==1):
|
||||||
|
GPIO.setup(pinnumber, GPIO.OUT)
|
||||||
|
elif(mode==0):
|
||||||
|
GPIO.setup(pinnumber, GPIO.IN)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def read_pin(pinnumber):
|
||||||
|
ret = 0
|
||||||
|
val = GPIO.input(pinnumber)
|
||||||
|
ret = int(val)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def write_pin(pinnumber, val):
|
||||||
|
#print("dummy: sending {} on {}".format(pinnumber, val))
|
||||||
|
|
||||||
|
if(val==1):
|
||||||
|
GPIO.output(pinnumber,GPIO.HIGH)
|
||||||
|
else:
|
||||||
|
GPIO.output(pinnumber,GPIO.LOW)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
#3-wire software-defined terminal class
|
||||||
|
#mirrors the logic of the arduino class, for talking with
|
||||||
|
#arduino-nano controlled perhipheral devices
|
||||||
|
class amsswcomm():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def comminit(self, _ms, _clkpin, _sendpin, _recvpin, _divisor = 1):
|
||||||
|
|
||||||
|
self.ms = int(_ms)
|
||||||
|
self.clkpin = int(_clkpin)
|
||||||
|
self.sendpin = int(_sendpin)
|
||||||
|
self.recvpin = int(_recvpin)
|
||||||
|
self.divisor = _divisor
|
||||||
|
|
||||||
|
|
||||||
|
self.sendmessage = np.uint8([])
|
||||||
|
self.recvmessage = np.uint8([])
|
||||||
|
|
||||||
|
self.clearrecvqueue()
|
||||||
|
self.clearsendqueue()
|
||||||
|
|
||||||
|
self.clockstate = 0
|
||||||
|
self.lastclockstate = 0
|
||||||
|
self.clockticks = 0
|
||||||
|
|
||||||
|
if(self.ms==1):
|
||||||
|
#master, most often the case for the raspberry pi
|
||||||
|
set_pinmode(self.clkpin,1)
|
||||||
|
set_pinmode(self.recvpin,0)
|
||||||
|
set_pinmode(self.sendpin,1)
|
||||||
|
|
||||||
|
elif(self.ms==0):
|
||||||
|
#servant
|
||||||
|
set_pinmode(self.clkpin,0)
|
||||||
|
set_pinmode(self.recvpin,0)
|
||||||
|
set_pinmode(self.sendpin,1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def update_step(self):
|
||||||
|
|
||||||
|
if(self.ms==1):
|
||||||
|
#master, most often the case for the raspberry pi
|
||||||
|
if(self.clockticks<self.divisor):
|
||||||
|
self.clockticks = self.clockticks+1
|
||||||
|
else:
|
||||||
|
self.clockticks = 0
|
||||||
|
|
||||||
|
self.lastclockstate = self.clockstate
|
||||||
|
self.clockstate = int(not self.lastclockstate)
|
||||||
|
|
||||||
|
write_pin(self.clkpin,self.clockstate)
|
||||||
|
|
||||||
|
if(self.clockstate==1 and self.lastclockstate==0):
|
||||||
|
self.update_send()
|
||||||
|
if(self.clockstate==0 and self.lastclockstate==1):
|
||||||
|
self.update_recv()
|
||||||
|
|
||||||
|
elif(self.ms==0):
|
||||||
|
|
||||||
|
self.lastclockstate = self.clockstate
|
||||||
|
self.clockstate = read_pin(self.clkpin)
|
||||||
|
|
||||||
|
if(self.clockstate==1 and self.lastclockstate==0):
|
||||||
|
self.update_send()
|
||||||
|
if(self.clockstate==0 and self.lastclockstate==1):
|
||||||
|
self.update_recv()
|
||||||
|
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def clearrecvqueue(self):
|
||||||
|
|
||||||
|
self.recvmessage_byte = np.uint16(0)
|
||||||
|
self.recvbytepointer = 0
|
||||||
|
self.recvbitpointer = 0
|
||||||
|
self.recvstate = 0
|
||||||
|
self.recvmessage = np.uint8([])
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def clearsendqueue(self):
|
||||||
|
|
||||||
|
self.sendmessage_byte = np.uint16(0)
|
||||||
|
self.sendbytepointer = 0
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendstate = 0
|
||||||
|
self.sendmessage = np.uint8([])
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def update_send(self):
|
||||||
|
|
||||||
|
if(self.sendstate==0):
|
||||||
|
#do nothing, no message in queue
|
||||||
|
write_pin(self.sendpin,0)
|
||||||
|
elif(self.sendstate==1):
|
||||||
|
self.sendmessage_byte = 0b0000001111111111
|
||||||
|
bit = (self.sendmessage_byte & 1<<(9-self.sendbitpointer)) >> (9-self.sendbitpointer)
|
||||||
|
|
||||||
|
write_pin(self.sendpin,bit)
|
||||||
|
|
||||||
|
self.sendbitpointer = self.sendbitpointer+1
|
||||||
|
if(self.sendbitpointer>=10):
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendbytepointer = 0
|
||||||
|
self.sendstate = 2
|
||||||
|
|
||||||
|
elif(self.sendstate==2):
|
||||||
|
#send message byte
|
||||||
|
if(len(self.sendmessage)>=0):
|
||||||
|
self.sendmessage_byte = 0b0000001100000000 + self.sendmessage[self.sendbytepointer]
|
||||||
|
bit = (self.sendmessage_byte & 1<<(9-self.sendbitpointer)) >> (9-self.sendbitpointer)
|
||||||
|
write_pin(self.sendpin,bit)
|
||||||
|
|
||||||
|
self.sendbitpointer = self.sendbitpointer + 1
|
||||||
|
if(self.sendbitpointer>=10):
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendbytepointer = self.sendbytepointer + 1
|
||||||
|
if(self.sendbytepointer>=len(self.sendmessage)):
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendbytepointer = 0
|
||||||
|
self.sendstate = 3
|
||||||
|
else:
|
||||||
|
#size 0 message
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendbytepointer = 0
|
||||||
|
self.sendstate = 3
|
||||||
|
|
||||||
|
elif(self.sendstate==3):
|
||||||
|
#send ending byte
|
||||||
|
self.sendmessage_byte = 0
|
||||||
|
bit = (self.sendmessage_byte & 1<<(9-self.sendbitpointer)) >> (9-self.sendbitpointer)
|
||||||
|
write_pin(self.sendpin,bit)
|
||||||
|
|
||||||
|
self.sendbitpointer = self.sendbitpointer+1
|
||||||
|
if(self.sendbitpointer>=10):
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendbytepointer = 0
|
||||||
|
self.sendstate = 4
|
||||||
|
|
||||||
|
|
||||||
|
elif(self.sendstate==4):
|
||||||
|
#Finish and reset
|
||||||
|
self.clearsendqueue()
|
||||||
|
else:
|
||||||
|
#improper condition, should not occur
|
||||||
|
self.clearsendqueue()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def update_recv(self):
|
||||||
|
|
||||||
|
if(self.recvstate==0):
|
||||||
|
bit = read_pin(self.recvpin)
|
||||||
|
if(bit==1):
|
||||||
|
self.recvstate = 1
|
||||||
|
self.recvbitpointer = 1
|
||||||
|
self.recvmessage_byte = 0b0000001000000000
|
||||||
|
self.recvbytepointer = 0
|
||||||
|
|
||||||
|
elif(self.recvstate==1):
|
||||||
|
bit = read_pin(self.recvpin)
|
||||||
|
self.recvmessage_byte = self.recvmessage_byte + (bit<<(9-self.recvbitpointer));
|
||||||
|
self.recvbitpointer = self.recvbitpointer + 1
|
||||||
|
|
||||||
|
if(self.recvbitpointer>=10):
|
||||||
|
self.recvbitpointer = 0
|
||||||
|
if(self.recvmessage_byte == 0b0000001111111111):
|
||||||
|
self.recvstate = 2
|
||||||
|
self.recvbytepointer = 0
|
||||||
|
|
||||||
|
#append to message
|
||||||
|
#byte2 = np.uint8(self.recvmessage_byte & 0b0000000011111111)
|
||||||
|
#self.recvmessage = np.append(self.recvmessage,byte2)
|
||||||
|
|
||||||
|
self.recvmessage_byte = 0
|
||||||
|
else:
|
||||||
|
#garbled message
|
||||||
|
self.clearrecvqueue()
|
||||||
|
|
||||||
|
elif(self.recvstate==2):
|
||||||
|
#receive messsage byte
|
||||||
|
bit = read_pin(self.recvpin)
|
||||||
|
self.recvmessage_byte = self.recvmessage_byte + (bit<<(9-self.recvbitpointer));
|
||||||
|
self.recvbitpointer = self.recvbitpointer + 1
|
||||||
|
|
||||||
|
if(self.recvbitpointer>=10):
|
||||||
|
self.recvbitpointer = 0
|
||||||
|
|
||||||
|
if(self.recvmessage_byte==0):
|
||||||
|
#end of message byte
|
||||||
|
self.recmessage_byte = 0
|
||||||
|
self.recvstate = 3
|
||||||
|
else:
|
||||||
|
#append to message
|
||||||
|
byte2 = np.uint8(self.recvmessage_byte & 0b0000000011111111)
|
||||||
|
self.recvmessage = np.append(self.recvmessage,byte2)
|
||||||
|
self.recvmessage_byte = 0
|
||||||
|
|
||||||
|
#DEBUG
|
||||||
|
# if(len(self.recvmessage)>10):
|
||||||
|
# self.recmessage_byte = 0
|
||||||
|
# self.recvstate = 3
|
||||||
|
|
||||||
|
elif(self.recvstate==3):
|
||||||
|
#has a message, - wait until this is handled
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
#invalid state
|
||||||
|
self.clearrecvqueue()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def has_message(self):
|
||||||
|
ret = False
|
||||||
|
|
||||||
|
if(self.recvstate==3):
|
||||||
|
ret = True
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def recv_message(self):
|
||||||
|
|
||||||
|
message = None
|
||||||
|
if(self.has_message()):
|
||||||
|
message = self.recvmessage
|
||||||
|
self.clearrecvqueue()
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
|
def send_message(self,message):
|
||||||
|
|
||||||
|
ret = False
|
||||||
|
|
||||||
|
if(type(message) is type(str)):
|
||||||
|
message = message.decode("utf-8")
|
||||||
|
if(type(message) is type(bytes)):
|
||||||
|
message = np.frombuffer(message,dtype=np.uint8)
|
||||||
|
|
||||||
|
if(self.sendstate==0):
|
||||||
|
ret = True
|
||||||
|
self.sendmessage = message
|
||||||
|
self.sendstate = 1
|
||||||
|
self.sendmessage_byte = 0
|
||||||
|
self.sendbitpointer = 0
|
||||||
|
self.sendbytepointer = 0
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os,sys,math
|
||||||
|
import numpy as np
|
||||||
|
from amsswcomm import *
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
GPIO.setmode(GPIO.BOARD);
|
||||||
|
#other mode is GPIO.BCM - pin numberings are different?
|
||||||
|
|
||||||
|
com = amsswcomm()
|
||||||
|
com.comminit(1,3,7,5,4)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while(True):
|
||||||
|
|
||||||
|
msg = input("Cmd: ")
|
||||||
|
msgb = msg.encode(encoding="utf-8")
|
||||||
|
msgb = np.frombuffer(msgb, dtype=np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
t0 = time.time()
|
||||||
|
t = time.time()
|
||||||
|
com.send_message(msgb)
|
||||||
|
while(com.has_message()==False and (t<t0+1)):
|
||||||
|
com.update_step()
|
||||||
|
t = time.time()
|
||||||
|
|
||||||
|
|
||||||
|
reply = com.recv_message()
|
||||||
|
print("reply: {}".format(reply))
|
Loading…
Reference in New Issue