'{$STAMP BS2SX} '' '' Programmer: Craig Stuart Sapp '' Programmer: Florian Vogt '' Creation Date: Sat 4 Dec 1999 '' Last Modified: Sun 19 Dec 1999 '' Filename: max3110.bsx '' Syntax: Basic Stamp IIsx '' '' Description: This program demonstrates how to receive and send '' MIDI data using the Maxim 3110 serial UART chip. '' This program just echos the input data it receives '' back to MIDI output (acting like MIDI thru). '' MIDI output is just sent from a BS2SX pin and not through '' the UART, since it will be a little faster to do so '' (the UART need 16 bits to transfer 8 bits of data). '' '' The MAX3110 chip can buffer up to 8 bytes of input '' data and 8 bytes of output. '' '' MIDI INPUT LIMITATIONS: '' '' There are limitations to MIDI input on the Basic Stamp IIsx microcontroller. '' The fastest synchronous serial transfer speed is 42k. The MAX3110 UART '' sends 8 bits of status information with every byte of data transfered '' between itself and the BS2SX; therefore, the effective fastest transfer rate '' of data between the MAX3110 chip and the BS2SX is 21k. The rate for MIDI is '' 31.25k which is faster than the transfer rate between the MAX3100 chip and '' the BS2SX, so you cannot use this setup for dense MIDI data transfers. '' '' The measured limitation of this setup is: '' '' No more than 9 MIDI bytes (3 MIDI messages) can follow each other '' in succession without placing a gap so that the data can be read from '' the UART's 8-byte input buffer. The minimum gap after three bytes should '' be greater than 36 milliseconds, or 39 milliseconds after the first of the '' three successive messages has been received. '' ' Constants for various settings: msb con 1 ' mode for shiftout functions behindclock con 2 ' sync mode for shiftin: msb post clock (falling edge) aheadclock con 0 ' sync mode for shiftin: msb pre clock (rising edge) midispeed con 60 ' baude mode for serout: (2500000/31250)-20 msec ' note that this value should be 12 for BS2. ' Serial rate for MIDI is 31,250 data bits/sec. outpause con 0 ' pause time for serout in units of 0.4 millisec. ' note: on the BS2 the units are 1.0 millisec. ' Pin definitions which specify the I/O ports being used on the Basic Stamp: MidiOutPin con 10 ' serial line for sending MIDI data UartIrqPin var IN11 ' IRQ line from MAX3110 indicating data waiting SelectUartPin con 12 ' chipselect for MAX3110 chip (0 selects) ClockPin con 13 ' synchronous clock pin to control MAX3110 chip UartInputPin con 14 ' for reading data from MAX3110 chip UartOutputPin con 15 ' for sending the controlbyte to the MAX3110 chip ' According to BASIC Stamp Programming Manual v1.9, page 208: ' "Unused pins that are not connected to circuitry should be set to output" ' to minimize power consumption, which is done here: DIRS = %1011011111111111 ' Don't set pins connected to input circuitry to be output, or you can ' damage the Basic Stamp. Note that msbit = pin #15 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' INIT: gosub UartConfigSub TOP: ' loop while waiting for an interrupt from the UART indicating new data if UartIrqPin = 1 then TOP ' at this point the UART has sent an interrupt because it has data ready, ' so read the data and then echo it to the MIDI output cable. gosub MidiReadSub debug hex ? midibytein midibyteout = midibytein gosub MidiWriteSub goto TOP end ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''' '' '' MidiReadSub -- Read one byte from the UART chip. This subroutine '' should be called after the UART chip sends an interrupt (changes line '' UartIrqPin from 1 to 0). This subroutine will write the '' MIDI input byte into the variable location "midibytein". '' ' ' SHIFTIN inputpin, clockpin, mode, [variable \ bits] ' inputin = pin to receive synchronous data on ' clockpin = pin to send synchronous clock signal ' mode = 0=MSB clock rising edge, 1=LSB/rise, 2=MSB/fall, 3=LSB/fall ' variable = location to store the bits ' bits = number of bits to input (default = 8); ' MidiReadSub: midibytein var byte ' MIDI input byte written in MidiReadSub statusbyte var byte ' UART diagnostics (ignored for now) ' activate the sychronous line to the UART low SelectUartPin ' read the 8 bit status byte from the UART shiftin UartInputPin, ClockPin, aheadclock, [statusbyte \ 8] ' read the 8 bit MIDI data from the UART shiftin UartInputPin, ClockPin, aheadclock, [midibytein \ 8] ' deselect the UART so that it updates the IRQ line high SelectUartPin return '''''''''''''''''''''''''''''' '' '' MidiWriteSub -- Writes a byte to the MIDI output pin. '' the output byte is expected to be in the variable '' location "midibyteout". '' ' ' SEROUT outputpin, baudemode, pause, [data] ' outputpin = pin on which to send serial data ' baudmode = asyncronous transfer rate ' pause = wait period between bytes in output (optional) ' data = one or more bytes/variables to send out. ' MidiWriteSub: midibyteout var byte ' location for MIDI output byte read in MidiWriteSub serout MidiOutPin, midispeed, outpause, [midibyteout] return '''''''''''''''''''''''''''''' '' '' UartConfigSub -- sends the configuration command to the '' MAX3110 chip. The MAX3110 read configuration control word below '' is composed of several fields in 16 bits, listed here from MSB to '' LSB bits. To activate the write command, the chip select must be '' turned on. Then after these 16 bits have been transfered, you need '' to deselect the MAX3110 chip so that the bits will be written into '' the MAX3100 configuration register. '' '' bit15-14: 11 = indicates that a configuration is being sent '' bit13: 0 = enable buffer on UART '' bit12: 0 = no software shutdown '' bit11: 0 = disable interrupt if output buffer is empty '' bit10: 1 = enable interrupt for input buffer data received '' bit9: 0 = don't worry about parity thing '' bit8: 0 = disable interrupt for shutdown or framing errs (see bit 12) '' bit7: 0 = no infrared data transfer '' bit6: 0 = 1 stop bits '' bit5: 0 = no parity '' bit4: 0 = 8 bit transmission '' bit3-0: 0011 = baud rate devisor select bits (for MIDI data rate) '' Baudrate * Prescale = UARTClock / divisor '' for a 4MHz UARTClock: 31250Hz * 16 = 4MHz / divisor '' and divisor = 8. See Table 6 in Maxim3110 datasheet '' p.20 for divisor codes used here. UartConfigSub: command1 con %11000100 ' bits 15-8 of the command word command2 con %00000011 ' bits 7-0 of the command word ' activate communication to the UART low SelectUartPin ' send the configuration bytes to the UART to set up for receiving MIDI input shiftout UartOutputPin, ClockPin, msb, [command1 \ 8] shiftout UartOutputPin, ClockPin, msb, [command2 \ 8] ' In order for the configuration to be written to the ' UART's command register, you must unselect the UART chip high SelectUartPin ' read back the configuration from the UART which just got written. ' it should be the same as the data in command1 and command2 ' except for the first two bits which are not part of the configuration. ' 'configuration var word ' holds the configuration word for verification 'low SelectUartPin 'shiftout UartOutputPin, ClockPin, msb, [%01\2] ' requests config register 'shiftin UartInputPin, ClockPin, aheadclock, [configuration\14] 'high SelectUartPin 'debug bin ? configuration return