401 lines
11 KiB
C++
401 lines
11 KiB
C++
#include "Arduino.h"
|
|
|
|
|
|
bool use_rn=false; //if use_rn=true, CR and LF only do what they say. if use_rn=false \r is ignored and \n does CRLF(=Enter)
|
|
|
|
//Arduino 1.8.3
|
|
//STM32F103C, 64k flash
|
|
//upload method: serial (A9 to RX, A10 to TX)
|
|
//To upload set Boot0 jumper to 1 (the one further away from reset btn) and press reset (stm will boot from flash wich contains uart to flash uploader)
|
|
//To boot program after restart set Boot0 jumper to 0
|
|
|
|
//#define DEBUG
|
|
|
|
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
|
|
|
|
void checkSerial();
|
|
bool textAvailable();
|
|
bool checkTextbuffer();
|
|
void sendChar(char c,char c2);
|
|
void coilInterrupt();
|
|
|
|
//pins die nicht gehn als output:
|
|
/* PA15
|
|
* PB3
|
|
* PB4
|
|
* PA12
|
|
*/
|
|
|
|
|
|
#if defined(BROTHERAX240)
|
|
#define SCAN_0 PA1
|
|
#define SCAN_1 PA2
|
|
#define SCAN_2 PA3
|
|
#define SCAN_3 PA4
|
|
#define SCAN_4 PA5
|
|
#define SCAN_5 PA6
|
|
#define SCAN_6 PA7
|
|
#define SCAN_7 PB0
|
|
#define SCAN_8 PB1
|
|
#define IN_A PB13
|
|
#define IN_B PB14
|
|
#define IN_C PB15
|
|
#define IN_D PB5
|
|
#define IN_E PB6
|
|
#define IN_F PB7
|
|
#define IN_G PB8
|
|
#define IN_H PB9
|
|
#elif defined(BROTHERAX130)
|
|
#define SCAN_0 PA1
|
|
#define SCAN_1 PA2
|
|
#define SCAN_2 PA3
|
|
#define SCAN_3 PA4
|
|
#define SCAN_4 PA5
|
|
#define SCAN_5 PA6
|
|
#define SCAN_6 PA7
|
|
#define SCAN_7 PB0
|
|
//#define SCAN_8 PB1
|
|
#define IN_A PB13
|
|
#define IN_B PB14
|
|
#define IN_C PB15
|
|
#define IN_D PB5
|
|
#define IN_E PB6
|
|
#define IN_F PB7
|
|
#define IN_G PB8
|
|
#define IN_H PB9
|
|
#endif
|
|
|
|
|
|
#define PIN_LED PC13
|
|
|
|
|
|
#if !defined(PIN_COIL_SENSE)
|
|
#define PIN_COIL_SENSE PB11
|
|
#endif
|
|
|
|
#define LEDON LOW
|
|
#define LEDOFF HIGH
|
|
|
|
|
|
#if defined(BROTHERAX240)
|
|
#define NUM_SCANPINS 9
|
|
int scanaddress[]={SCAN_0,SCAN_1,SCAN_2,SCAN_3,SCAN_4,SCAN_5,SCAN_6,SCAN_7,SCAN_8};
|
|
#define NUM_INADDR 8
|
|
int inaddress[]={IN_A,IN_B,IN_C,IN_D,IN_E,IN_F,IN_G,IN_H};
|
|
|
|
#include "matrix_ax240.h"
|
|
#elif defined(BROTHERAX130)
|
|
#define NUM_SCANPINS 8
|
|
int scanaddress[]={SCAN_0,SCAN_1,SCAN_2,SCAN_3,SCAN_4,SCAN_5,SCAN_6,SCAN_7};
|
|
#define NUM_INADDR 8
|
|
int inaddress[]={IN_A,IN_B,IN_C,IN_D,IN_E,IN_F,IN_G,IN_H};
|
|
|
|
#include "matrix_ax130.h"
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define TEXTBUFFERSIZE 8192
|
|
byte textbuffer[TEXTBUFFERSIZE]; //ca 60-65 Zeilen pro DinA4, a 65 characters (10 Pica), 78 characters (12 Elite) or 97 characters (15 Mikron)
|
|
uint16_t bufferpos_write=0;
|
|
uint16_t bufferpos_read=0;
|
|
|
|
|
|
#define DELAY_KEYPRESS 100 //delay in ms between keypresses
|
|
long last_keypress=0;
|
|
|
|
bool linefeed_used=false; //if Linefeed key was used CR (CODE+Enter) must be pressed twice for full CR
|
|
|
|
volatile uint16_t count_bufferedchars=0; //keeps track of buffered characters on the typewriter
|
|
#define MAX_TYPEWRITER_BUFFERCOUNT 2
|
|
#define MAXIMUM_COILWAIT 5000 //if no interrupt from coil received decrease buffer count after this time (in ms)
|
|
|
|
void setup() {
|
|
|
|
if (use_rn) { //change matrix mapping if CR and LF are used
|
|
#if defined(BROTHERAX240)
|
|
byte _km10[NUM_SCANPINS]={0,0,16,0,0,0,0,0,0}; //10 = [LINE FEED]
|
|
byte _km13[NUM_SCANPINS]={0,36,0,0,0,0,0,0,0}; //13 = [CARRIAGE RETURN]
|
|
#elif defined(BROTHERAX130)
|
|
byte _km10[NUM_SCANPINS]={0,64,0,0,0,0,0,0}; //10 = [LINE FEED]
|
|
byte _km13[NUM_SCANPINS]={0,0,0,0,0,0,0,0}; //13 = [CARRIAGE RETURN]
|
|
#endif
|
|
|
|
for (uint8_t i=0;i<NUM_SCANPINS;i++){ //copy array content
|
|
keymatrix[10][i]=_km10[i];
|
|
keymatrix[13][i]=_km13[i];
|
|
}
|
|
}
|
|
|
|
Serial1.begin(9600);
|
|
|
|
#if defined(BROTHERAX240)
|
|
pinMode(SCAN_0,INPUT_PULLUP);
|
|
pinMode(SCAN_1,INPUT_PULLUP);
|
|
pinMode(SCAN_2,INPUT_PULLUP);
|
|
pinMode(SCAN_3,INPUT_PULLUP);
|
|
pinMode(SCAN_4,INPUT_PULLUP);
|
|
pinMode(SCAN_5,INPUT_PULLUP);
|
|
pinMode(SCAN_6,INPUT_PULLUP);
|
|
pinMode(SCAN_7,INPUT_PULLUP);
|
|
pinMode(SCAN_8,INPUT_PULLUP);
|
|
|
|
pinMode(IN_A,OUTPUT);
|
|
pinMode(IN_B,OUTPUT);
|
|
pinMode(IN_C,OUTPUT);
|
|
pinMode(IN_D,OUTPUT);
|
|
pinMode(IN_E,OUTPUT);
|
|
pinMode(IN_F,OUTPUT);
|
|
pinMode(IN_G,OUTPUT);
|
|
pinMode(IN_H,OUTPUT);
|
|
|
|
digitalWrite(IN_A,LOW);
|
|
digitalWrite(IN_B,LOW);
|
|
digitalWrite(IN_C,LOW);
|
|
digitalWrite(IN_D,LOW);
|
|
digitalWrite(IN_E,LOW);
|
|
digitalWrite(IN_F,LOW);
|
|
digitalWrite(IN_G,LOW);
|
|
digitalWrite(IN_H,LOW);
|
|
#elif defined(BROTHERAX130)
|
|
pinMode(SCAN_0,INPUT_PULLUP);
|
|
pinMode(SCAN_1,INPUT_PULLUP);
|
|
pinMode(SCAN_2,INPUT_PULLUP);
|
|
pinMode(SCAN_3,INPUT_PULLUP);
|
|
pinMode(SCAN_4,INPUT_PULLUP);
|
|
pinMode(SCAN_5,INPUT_PULLUP);
|
|
pinMode(SCAN_6,INPUT_PULLUP);
|
|
pinMode(SCAN_7,INPUT_PULLUP);
|
|
//pinMode(SCAN_8,INPUT_PULLUP);
|
|
|
|
pinMode(IN_A,OUTPUT);
|
|
pinMode(IN_B,OUTPUT);
|
|
pinMode(IN_C,OUTPUT);
|
|
pinMode(IN_D,OUTPUT);
|
|
pinMode(IN_E,OUTPUT);
|
|
pinMode(IN_F,OUTPUT);
|
|
pinMode(IN_G,OUTPUT);
|
|
pinMode(IN_H,OUTPUT);
|
|
|
|
digitalWrite(IN_A,LOW);
|
|
digitalWrite(IN_B,LOW);
|
|
digitalWrite(IN_C,LOW);
|
|
digitalWrite(IN_D,LOW);
|
|
digitalWrite(IN_E,LOW);
|
|
digitalWrite(IN_F,LOW);
|
|
digitalWrite(IN_G,LOW);
|
|
digitalWrite(IN_H,LOW);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pinMode(PIN_COIL_SENSE, INPUT_PULLUP);
|
|
attachInterrupt(PIN_COIL_SENSE, coilInterrupt, RISING); //pin pulled low if coil powered
|
|
|
|
|
|
pinMode(PIN_LED,OUTPUT);
|
|
digitalWrite(PIN_LED,LEDON);
|
|
delay(500);
|
|
digitalWrite(PIN_LED,LEDOFF);
|
|
|
|
Serial1.println("Brother AX Serialmod");
|
|
|
|
}
|
|
|
|
void loop() {
|
|
checkSerial(); //check serial buffer and write to textbuffer
|
|
|
|
if (millis()>last_keypress+DELAY_KEYPRESS){
|
|
|
|
if (count_bufferedchars<MAX_TYPEWRITER_BUFFERCOUNT) //wait if too many chars are send to typewriter buffer
|
|
{
|
|
bool charsend=checkTextbuffer(); //check one character from serial buffer and send to typewriter
|
|
//Serial1.print(6); //Send ACK
|
|
if (charsend){ //a character was actually sent
|
|
last_keypress=millis();
|
|
}
|
|
}
|
|
|
|
if (count_bufferedchars>0 && millis()>last_keypress+MAXIMUM_COILWAIT){ //coil response timeout
|
|
count_bufferedchars--; //decrease buffer count
|
|
last_keypress=millis();
|
|
}
|
|
|
|
}
|
|
|
|
if (count_bufferedchars>=MAX_TYPEWRITER_BUFFERCOUNT){
|
|
digitalWrite(PIN_LED,LEDON); //led on -> wait for buffer to empty
|
|
}else{
|
|
digitalWrite(PIN_LED,LEDOFF); //led off -> buffer isnt full
|
|
}
|
|
}
|
|
|
|
void checkSerial(){
|
|
while(Serial1.available()){
|
|
if (Serial1.available()>0){
|
|
char c=Serial1.read();
|
|
bufferpos_write++;
|
|
bufferpos_write%=TEXTBUFFERSIZE;
|
|
textbuffer[bufferpos_write]=c; //bufferpos_write points to last written char position
|
|
|
|
if (use_rn) {
|
|
if (c==10 || (c==13 && linefeed_used)) {
|
|
//char 10 is LineFeed. If emulated by pressing 2,4 (arrow down, top right of keyboard), key needs to be pressed twice to get one line spacing
|
|
//Also CR (CODE+Enter) must be pressed twice, if LineFeed key is used in the same Text Line
|
|
bufferpos_write++;
|
|
bufferpos_write%=TEXTBUFFERSIZE;
|
|
textbuffer[bufferpos_write]=c; //bufferpos_write points to last written char position
|
|
}
|
|
if (c==13) {
|
|
linefeed_used=false;
|
|
}else if(c==10){
|
|
linefeed_used=true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool textAvailable(){
|
|
if (bufferpos_write!=bufferpos_read){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool checkTextbuffer(){
|
|
bool returnvalue=false;
|
|
//while(Serial1.available()){
|
|
//if (Serial1.available()>0){
|
|
if (textAvailable()) { //buffer contains unread chars
|
|
bufferpos_read++;//bufferpos_read points to last read char position
|
|
bufferpos_read%=TEXTBUFFERSIZE;
|
|
char c = textbuffer[bufferpos_read];
|
|
|
|
#ifdef DEBUG
|
|
Serial1.print((uint8_t)c); //echo
|
|
Serial1.print("="); //echo
|
|
Serial1.println(c); //echo
|
|
#endif
|
|
|
|
if (c==195 || c==194) { //umlaut
|
|
#ifdef DEBUG
|
|
Serial1.print("Uml:");
|
|
#endif
|
|
|
|
while (!textAvailable()){ checkSerial(); } //wait for next byte and checkSerial in between
|
|
bufferpos_read++;//bufferpos_read points to last read char position
|
|
bufferpos_read%=TEXTBUFFERSIZE;
|
|
char c2=textbuffer[bufferpos_read];
|
|
#ifdef DEBUG
|
|
Serial1.println((uint8_t)c2); //echo
|
|
#endif
|
|
sendChar(c,c2); //2 byte character
|
|
returnvalue=true;
|
|
|
|
}else{
|
|
sendChar(c,0); //normal 1 byte character
|
|
returnvalue=true;
|
|
}
|
|
|
|
|
|
}
|
|
//}
|
|
|
|
|
|
|
|
return returnvalue; //true= character send, false=buffer was empty
|
|
}
|
|
|
|
void sendChar(char c,char c2) { //c2 =0 for 1 byte characters
|
|
uint8_t keypress[NUM_SCANPINS]={0}; //keypress contains id of input pin. 0=not pressed, A=2^0, B=2^1, C=2^3 ...
|
|
|
|
//check if key is implemented (not all 255,255,255,..)
|
|
bool keyimplemented=false;
|
|
for (uint8_t i=0;i<NUM_SCANPINS;i++){
|
|
if (keymatrix[c][i]!=0){
|
|
keyimplemented=true;
|
|
}
|
|
}
|
|
|
|
if (keyimplemented && ( (c>=32 && c<127) || c==10 || c==13 ) ) { //1 byte char
|
|
#ifdef DEBUG
|
|
Serial1.println("1 byte char");
|
|
#endif
|
|
for (uint8_t i=0;i<NUM_SCANPINS;i++){
|
|
keypress[i]=keymatrix[c][i]; //copy keypress connections for current char
|
|
}
|
|
}else if (c==195){ //umlauts
|
|
#ifdef DEBUG
|
|
Serial1.println("2 byte char");
|
|
#endif
|
|
for (uint8_t i=0;i<NUM_SCANPINS;i++){
|
|
keypress[i]=keymatrix195[c2][i]; //copy keypress connections for current char
|
|
}
|
|
}else if(c==194){ //others
|
|
if (c2==167){ // §
|
|
keypress[0]=128; keypress[7]=16; //shift + 3
|
|
}else if (c2==176){ // °
|
|
keypress[1]=32; keypress[3]=8; //CODE + W
|
|
}
|
|
}else if(c>=32){ //not recognized character (everything else) and not a control command
|
|
keypress[1]=128; // [SPACE] //print space to keep text aligned
|
|
}
|
|
|
|
|
|
//Update count buffered chars
|
|
if ((c>32 && c<127) ) { //pressed key uses hammer. (32 is space)
|
|
if (keyimplemented){ //keymatrix was implemented for c (not 255,255...)
|
|
count_bufferedchars++; //character send to typewriter. Increase character buffer count
|
|
}
|
|
}
|
|
|
|
//digitalWrite(PIN_LED,LEDON);
|
|
#define HOLDCYCLES 3
|
|
|
|
for (uint8_t hold=0;hold<HOLDCYCLES;hold++){ //cycles to hold the key
|
|
for (uint8_t i=0;i<NUM_SCANPINS;i++){
|
|
if (keypress[i]!=0){ //some key on scan i will be pressed
|
|
unsigned int scanaddr=scanaddress[i]; //get pin address for i SCAN_i
|
|
uint8_t keypresses=keypress[i];
|
|
|
|
while(digitalRead(scanaddr)){ }//wait while high
|
|
|
|
for (int b=0;b<NUM_INADDR;b++) { //set inaddress outputs to 1 bits from keypresses. Example: if keypresses=129, inaddress[0] and inaddress[7] will be used
|
|
if (CHECK_BIT(keypresses,b)) {
|
|
digitalWrite(inaddress[b],HIGH);
|
|
}
|
|
}
|
|
|
|
while(!digitalRead(scanaddr)){ } //wait while low
|
|
|
|
for (int b=0;b<NUM_INADDR;b++) { //set inaddress outputs to 1 bits from keypresses. Example: if keypresses=129, inaddress[0] and inaddress[7] will be used
|
|
if (CHECK_BIT(keypresses,b)) {
|
|
digitalWrite(inaddress[b],LOW); //set high -> transistor pulls input of printer to ground
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//digitalWrite(PIN_LED,LEDOFF);
|
|
}
|
|
|
|
void coilInterrupt(){
|
|
if (count_bufferedchars>0){
|
|
count_bufferedchars--;
|
|
}
|
|
}
|
|
|
|
|