TASCAM Sound Recorder (Part 4)
And here is the driver code. Nothing exceptional just plain good’ol arduino code. Check theĀ writeByte function which contains few tricks and optimizations that are mandatory to achieve a proper timing. Ultimately this code contains a pretty versatile bit-bang UART writer that you may want to reuse in various applications.
Enter the DR-40 commands through the key board of the console using the abbreviations from the commands:
- ‘p’: PLAY
- ‘s’: STOP
- ‘r’: RECORD
- ‘f’: FORWARD
- ‘b’: BACK
- ‘m’: MARK
- ‘1’: F1
- ‘2’: F2
- ‘3’: F3
- ‘4’: F4
uint8_t _TxMask; uint8_t _TxMaskBar; volatile uint8_t *_TxPort; uint16_t _timeInterval; bool _invert; bool _parity; #define ONE_MILLION 1000000UL #define STOP 0x08 #define PLAY 0x09 #define RECORD 0x0B #define FORWARD 0x0E #define BACK 0x0F #define MARK 0x18 #define F1 0x1C #define F2 0x1D #define F3 0x1E #define F4 0x1F #define KEY_PRESS 0x40 #define KEY_DOWN 0x60 #define KEY_UP 0x00 #define PAR_NONE 0x00 #define PAR_EVEN 0x01 #define PAR_ODD 0x02 /* Initialize communication port Any pin on any port can be used Baud rate goes up to 57600 Parity may be none (0), odd (1) or even (2) Data may be inverted or not (flip mark and spaces) */ void begin(volatile uint8_t *TxPort, uint8_t TxPin, uint32_t baudRate = 9600, uint8_t parity = PAR_NONE, bool invert = true) { /* Record global variables */ _invert = invert; _parity = parity; /* Transmit port */ _TxPort = TxPort; /* Transmit pin */ _TxMask = (0x01 << TxPin); _TxMaskBar = ~_TxMask; /* Make TxPin an output pin */ *(_TxPort - 1) |= _TxMask; /* Set idle mode */ if (!_invert) { *(_TxPort) |= _TxMask; } else { *(_TxPort) &= _TxMaskBar; } /* Set bits intervals in us */ _timeInterval = (ONE_MILLION / baudRate); } /* Write byte on serial port global variables in use: _parity _invert _TxPort _TxMask _TxMaskBar _timeInterval idle ----------- --- --- --- --- ---- --- ---- 1 mark |Sta| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |Par|Stp| --- --- --- --- --- --- 0 space/break */ void writeByte(const uint8_t data) { uint32_t now; uint16_t compositeBits = 0x00; /* Map data bits */ /* compositeBits content: 76543210 */ compositeBits |= data; /* Map data bits */ uint8_t bits = 8; if (_parity != PAR_NONE) { bool dataParity = parity(data); /* Append a mark as appropriate */ if (((_parity == PAR_EVEN) && dataParity) || ((_parity == PAR_ODD) && !dataParity)) { /* compositeBits content: p76543210 */ compositeBits |= (0x01 << bits); /* Map parity bit */ } bits += 1; /* Actually 9 bits */ } /* compositeBits content: Sp76543210 or S76543210*/ compositeBits |= (0x01 << bits); /* Map stop bit (mark) */ /* compositeBits content: Sp76543210s or S76543210s */ compositeBits <<= 1; /* Shift bits for start inclusion (space) */ bits += 2; if (_invert) { compositeBits= ~compositeBits; } uint32_t lastTick = micros(); /* Record start time of bits transfer */ /* Transfer composite bits starting from lower bits */ for (uint8_t i = 0; i < bits; i++) { uint8_t bitValue = (compositeBits & 0x01); /* Extract lower bit value */ if (bitValue) { *(_TxPort) |= _TxMask; } else { *(_TxPort) &= _TxMaskBar; } compositeBits >>= 1; /* Shift bits */ while((micros() - lastTick) < _timeInterval); lastTick += _timeInterval; /* Set next bit release time */ } } /* Send function key */ void sendKey(uint8_t function) { writeByte(function | KEY_PRESS); delay(150); writeByte(function | KEY_UP); } /* Computes the parity from a value. The function returns a true for an odd number of bits and a false for an even number of bits. */ bool parity(uint8_t n) { bool parity = 0; while (n) { parity = !parity; n = (n & (n - 1)); } return(parity); } void setup() { /* Configure serial port using default parameters */ begin(&PORTB, PINB0, 9600, PAR_EVEN, true); delay(500); Serial.begin(115200); } void loop() { /* Listen to incoming bytes from the console */ if (Serial.available() > 0) { char inputByte = (char)Serial.read(); switch(inputByte) { case 'p': sendKey(PLAY); break; case 's': sendKey(STOP); break; case 'r': sendKey(RECORD); break; case 'f': sendKey(FORWARD); break; case 'b': sendKey(BACK); break; case 'm': sendKey(MARK); break; case '1': sendKey(F1); break; case '2': sendKey(F2); break; case '3': sendKey(F3); break; case '4': sendKey(F4); break; } } delay(10); }