2022-02-13 12:37:40 +00:00
# include "Arduino.h"
2023-11-15 07:25:49 +00:00
2022-02-13 14:42:08 +00:00
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)
2022-01-17 19:28:56 +00:00
//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
2022-02-13 13:14:49 +00:00
# define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
2022-02-13 12:37:40 +00:00
void checkSerial ( ) ;
bool textAvailable ( ) ;
bool checkTextbuffer ( ) ;
void sendChar ( char c , char c2 ) ;
void coilInterrupt ( ) ;
2022-01-17 19:28:56 +00:00
//pins die nicht gehn als output:
/* PA15
* PB3
* PB4
* PA12
*/
2023-11-15 07:25:49 +00:00
# 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
2022-01-17 19:28:56 +00:00
# define PIN_LED PC13
2023-11-15 07:25:49 +00:00
# if !defined(PIN_COIL_SENSE)
# define PIN_COIL_SENSE PB11
# endif
2022-01-17 19:28:56 +00:00
# define LEDON LOW
# define LEDOFF HIGH
2023-11-15 07:25:49 +00:00
# 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
2022-01-17 19:28:56 +00:00
# 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 ;
2022-02-13 13:56:50 +00:00
bool linefeed_used = false ; //if Linefeed key was used CR (CODE+Enter) must be pressed twice for full CR
2022-01-17 19:28:56 +00:00
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 ( ) {
2022-02-13 14:42:08 +00:00
if ( use_rn ) { //change matrix mapping if CR and LF are used
2023-11-15 07:25:49 +00:00
# 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
2022-02-13 14:42:08 +00:00
for ( uint8_t i = 0 ; i < NUM_SCANPINS ; i + + ) { //copy array content
keymatrix [ 10 ] [ i ] = _km10 [ i ] ;
keymatrix [ 13 ] [ i ] = _km13 [ i ] ;
}
}
2022-01-17 19:28:56 +00:00
2022-02-13 14:42:08 +00:00
Serial1 . begin ( 9600 ) ;
2023-11-15 07:25:49 +00:00
# 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
2022-02-13 14:42:08 +00:00
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 ) ;
2023-11-15 07:25:49 +00:00
Serial1 . println ( " Brother AX Serialmod " ) ;
2022-01-17 19:28:56 +00:00
}
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
2022-02-13 13:28:10 +00:00
//Serial1.print(6); //Send ACK
2022-01-17 19:28:56 +00:00
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 ( ) {
2022-02-13 13:28:10 +00:00
while ( Serial1 . available ( ) ) {
if ( Serial1 . available ( ) > 0 ) {
2022-02-13 14:42:08 +00:00
char c = Serial1 . read ( ) ;
2022-02-13 13:56:50 +00:00
bufferpos_write + + ;
bufferpos_write % = TEXTBUFFERSIZE ;
textbuffer [ bufferpos_write ] = c ; //bufferpos_write points to last written char position
2022-02-13 14:42:08 +00:00
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 ;
}
}
2022-01-17 19:28:56 +00:00
}
}
}
bool textAvailable ( ) {
if ( bufferpos_write ! = bufferpos_read ) {
return true ;
}
return false ;
}
bool checkTextbuffer ( ) {
bool returnvalue = false ;
2022-02-13 13:28:10 +00:00
//while(Serial1.available()){
//if (Serial1.available()>0){
2022-01-17 19:28:56 +00:00
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
2022-02-13 13:28:10 +00:00
Serial1 . print ( ( uint8_t ) c ) ; //echo
Serial1 . print ( " = " ) ; //echo
Serial1 . println ( c ) ; //echo
2022-01-17 19:28:56 +00:00
# endif
if ( c = = 195 | | c = = 194 ) { //umlaut
# ifdef DEBUG
2022-02-13 13:28:10 +00:00
Serial1 . print ( " Uml: " ) ;
2022-01-17 19:28:56 +00:00
# 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
2022-02-13 13:28:10 +00:00
Serial1 . println ( ( uint8_t ) c2 ) ; //echo
2022-01-17 19:28:56 +00:00
# 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
2023-11-15 07:25:49 +00:00
uint8_t keypress [ NUM_SCANPINS ] = { 0 } ; //keypress contains id of input pin. 0=not pressed, A=2^0, B=2^1, C=2^3 ...
2022-01-17 19:28:56 +00:00
//check if key is implemented (not all 255,255,255,..)
bool keyimplemented = false ;
for ( uint8_t i = 0 ; i < NUM_SCANPINS ; i + + ) {
2022-02-13 13:14:49 +00:00
if ( keymatrix [ c ] [ i ] ! = 0 ) {
2022-01-17 19:28:56 +00:00
keyimplemented = true ;
}
}
if ( keyimplemented & & ( ( c > = 32 & & c < 127 ) | | c = = 10 | | c = = 13 ) ) { //1 byte char
# ifdef DEBUG
2022-02-13 13:28:10 +00:00
Serial1 . println ( " 1 byte char " ) ;
2022-01-17 19:28:56 +00:00
# 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
2022-02-13 13:28:10 +00:00
Serial1 . println ( " 2 byte char " ) ;
2022-01-17 19:28:56 +00:00
# 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 ) { // §
2022-02-13 13:14:49 +00:00
keypress [ 0 ] = 128 ; keypress [ 7 ] = 16 ; //shift + 3
2022-01-17 19:28:56 +00:00
} else if ( c2 = = 176 ) { // °
2022-02-13 13:14:49 +00:00
keypress [ 1 ] = 32 ; keypress [ 3 ] = 8 ; //CODE + W
2022-01-17 19:28:56 +00:00
}
} else if ( c > = 32 ) { //not recognized character (everything else) and not a control command
2022-02-13 13:14:49 +00:00
keypress [ 1 ] = 128 ; // [SPACE] //print space to keep text aligned
2022-01-17 19:28:56 +00:00
}
//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 + + ) {
2022-02-13 13:14:49 +00:00
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 ] ;
2022-01-17 19:28:56 +00:00
while ( digitalRead ( scanaddr ) ) { } //wait while high
2022-02-13 13:14:49 +00:00
2023-11-15 07:25:49 +00:00
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
2022-02-13 13:14:49 +00:00
if ( CHECK_BIT ( keypresses , b ) ) {
digitalWrite ( inaddress [ b ] , HIGH ) ;
}
}
while ( ! digitalRead ( scanaddr ) ) { } //wait while low
2023-11-15 07:25:49 +00:00
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
2022-02-13 13:14:49 +00:00
if ( CHECK_BIT ( keypresses , b ) ) {
digitalWrite ( inaddress [ b ] , LOW ) ; //set high -> transistor pulls input of printer to ground
}
}
2022-01-17 19:28:56 +00:00
}
}
}
//digitalWrite(PIN_LED,LEDOFF);
}
void coilInterrupt ( ) {
if ( count_bufferedchars > 0 ) {
count_bufferedchars - - ;
}
}
2022-02-13 12:37:40 +00:00