Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: FLIGHT_CONTROL_AND_COMMUNICATIONS_SYSTEM
Diff: MAX3100.cpp
- Revision:
- 0:055897ab699b
- Child:
- 1:46c8c60e744a
diff -r 000000000000 -r 055897ab699b MAX3100.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX3100.cpp Sun Jan 16 18:27:44 2011 +0000
@@ -0,0 +1,324 @@
+/*
+ Copyright (c) 2011 Andy Kirkham
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "MAX3100.h"
+
+namespace AjK {
+
+void
+MAX3100::init(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, SPI *spi)
+{
+ config = 0;
+ flushTxBuffer();
+ flushRxBuffer();
+
+ _parity = 0;
+
+ _cs_function = NULL;
+ _cs_obj = NULL;
+ _cs_method = NULL;
+
+ if (cs != NC) {
+ _cs = new DigitalOut(cs);
+ _cs->write( 1 );
+ }
+ else _cs = (DigitalOut *)NULL;
+
+ if (spi) {
+ _spi = spi;
+ }
+ else {
+ _spi = new SPI(mosi, miso, sclk);
+ _spi->format(16, 0);
+ _spi->frequency(MAX3100_SPI_FREQ);
+ }
+
+ if (irq != NC) {
+ _irq = new InterruptIn(irq);
+ _irq->mode(PullUp);
+ topic_1498(irq);
+ _irq->fall(this, &MAX3100::isr);
+ }
+ else { _irq = (InterruptIn *)NULL; }
+
+ baud(10); // 9600baud by default.
+}
+
+void
+MAX3100::cs_value(int i)
+{
+ if (_cs != (DigitalOut *)NULL) _cs->write(i & 1);
+ else {
+ if (_cs_function != NULL) (*_cs_function)(_device, i & 1);
+ else {
+ if (_cs_obj && _cs_method) (_cs_obj->*_cs_method)(_device, i & 1);
+ }
+ }
+}
+
+uint16_t
+MAX3100::spiwrite(uint16_t val)
+{
+ cs_value(0);
+ uint16_t r = _spi->write(val);
+ cs_value(1);
+ return r;
+}
+
+uint16_t
+MAX3100::config_write(uint16_t val)
+{
+ return spiwrite(MAX3100_CONF_WR | val);
+}
+
+uint16_t
+MAX3100::config_read(void)
+{
+ return spiwrite(MAX3100_CONF_RD);
+}
+
+
+void
+MAX3100::baud(int baudrate)
+{
+ __disable_irq();
+ config &= ~(0xf);
+ config |= (baudrate & 0xf);
+ config_write(config);
+ __enable_irq();
+}
+
+void
+MAX3100::enableRxIrq(void)
+{
+ __disable_irq();
+ config &= ~MAX3100_RM(1);
+ config |= MAX3100_RM(1);
+ config_write(config);
+ __enable_irq();
+}
+
+void
+MAX3100::disableRxIrq(void)
+{
+ __disable_irq();
+ config &= ~MAX3100_RM(1);
+ config_write(config);
+ __enable_irq();
+}
+
+void
+MAX3100::enableTxIrq(void)
+{
+ __disable_irq();
+ config &= ~MAX3100_TM(1);
+ config |= MAX3100_TM(1);
+ config_write(config);
+ __enable_irq();
+}
+
+void
+MAX3100::disableTxIrq(void)
+{
+ __disable_irq();
+ config &= ~MAX3100_TM(1);
+ config_write(config);
+ __enable_irq();
+}
+
+int
+MAX3100::putc(int c)
+{
+ uint16_t data, conf;
+
+ // If no space return -1 as an error code.
+ if (tx_buffer_full) return -1;
+
+ if (_parity) {
+ int pBit = parityCal(c & 0xFF);
+ if (_parity == Even && pBit == 0) { c |= (1 << 8); }
+ if (_parity == Odd && pBit == 1) { c |= (1 << 8); }
+ }
+ else { c &= 0xFF; }
+
+ // Function is non-interruptable by the MAX3100 class
+ // to avoid SPI bus contention between writing a byte
+ // in user context (here) and IRQ context.
+ __disable_irq();
+
+ conf = config_read();
+
+ if (tx_buffer_in == tx_buffer_out && conf & MAX3100_CONF_T) {
+ data = spiwrite(MAX3100_DATA_WR | (c & 0x1FF));
+ // In case we get a byte while writing store it away.
+ if (!rx_buffer_full && data & MAX3100_CONF_R) {
+ rx_buffer[rx_buffer_in++] = (uint16_t)(data & 0xFF);
+ if (rx_buffer_in >= MAX3100_RX_BUFFER_SIZE) rx_buffer_in = 0;
+ if (rx_buffer_in == rx_buffer_out) rx_buffer_full = true;
+ }
+ }
+ else {
+ tx_buffer[tx_buffer_in++] = (char)(c & 0xFF);
+ if (tx_buffer_in >= MAX3100_TX_BUFFER_SIZE) {
+ tx_buffer_in = 0;
+ }
+ if (tx_buffer_in == tx_buffer_out) tx_buffer_full = true;
+ }
+
+ __enable_irq();
+
+ return 1;
+}
+
+void
+MAX3100::puts(char *s) {
+ char *q = s;
+ while(*(q)) {
+ if (putc((int)(*(q))) == -1) return;
+ q++;
+ }
+}
+
+int
+MAX3100::getc(void) {
+ if (!rx_buffer_full && rx_buffer_in == rx_buffer_out) return -1;
+ int c = (int)((unsigned char)rx_buffer[rx_buffer_out++]);
+ if (rx_buffer_out >= MAX3100_RX_BUFFER_SIZE) rx_buffer_out = 0;
+ rx_buffer_full = false;
+ return c;
+}
+
+char *
+MAX3100::gets(char *s, int size)
+{
+ int i;
+ char *q = s;
+ while(size) {
+ do { i = getc(); } while (i == -1); // Blocks!
+ *(q) = (char)i; size--;
+ }
+ return s;
+}
+
+int
+MAX3100::peek(void) {
+ if (!rx_buffer_full && rx_buffer_in == rx_buffer_out) return -1;
+ return (int)((unsigned char)rx_buffer[rx_buffer_out]);
+}
+
+void
+MAX3100::isr(void) {
+ uint16_t data = spiwrite(MAX3100_DATA_RD);
+ bool tx_ready = data & MAX3100_CONF_T ? true : false;
+
+ // The MAX3100 does have an RX fifo. So attempt to empty it into the RX buffer.
+ do {
+ if (!rx_buffer_full && data & MAX3100_CONF_R) {
+ rx_buffer[rx_buffer_in++] = (char)(data & 0xFF);
+ if (rx_buffer_in >= MAX3100_RX_BUFFER_SIZE) rx_buffer_in = 0;
+ if (rx_buffer_in == rx_buffer_out) rx_buffer_full = true;
+ }
+ }
+ while ((data = spiwrite(MAX3100_DATA_RD)) & MAX3100_CONF_R);
+
+ // The MAX3100 doesn't have a hardware TX fifo, so just test to see if it's TX buffer
+ // is empty. If it is and we have bytes in the TX buffer then send one now.
+ if (tx_ready && (tx_buffer_full || tx_buffer_in != tx_buffer_out)) {
+ data = spiwrite(MAX3100_DATA_WR | (tx_buffer[tx_buffer_out++] & 0x1FF));
+ if (tx_buffer_out >= MAX3100_TX_BUFFER_SIZE) tx_buffer_out = 0;
+ tx_buffer_full = false;
+ }
+
+ // In case we get a byte while sending then store it.
+ if (!rx_buffer_full && data & MAX3100_CONF_R) {
+ rx_buffer[rx_buffer_in++] = (char)(data & 0xFF);
+ if (rx_buffer_in >= MAX3100_RX_BUFFER_SIZE) rx_buffer_in = 0;
+ if (rx_buffer_in == rx_buffer_out) rx_buffer_full = true;
+ }
+}
+
+void
+MAX3100::setStopBits(int i)
+{
+ switch(i) {
+ case 1:
+ __disable_irq();
+ config &= ~(1 << 6);
+ config_write(config);
+ __enable_irq();
+ break;
+ case 2:
+ __disable_irq();
+ config |= (1 << 6);
+ config_write(config);
+ __enable_irq();
+ break;
+ }
+}
+
+int
+MAX3100::parityCal(uint8_t c)
+{
+ int count = 0;
+ for (int mask = 1, i = 0; i < 8; i++, mask = mask << 1) {
+ if (c & mask) count++;
+ }
+ return count & 1;
+}
+
+void
+MAX3100::topic_1498(PinName p) {
+ // http://mbed.org/forum/bugs-suggestions/topic/1498
+ uint32_t clr0 = 0, clr2 = 0;
+
+ switch( p ) {
+ case p5: clr0 = (1UL << 9); break;
+ case p6: clr0 = (1UL << 8); break;
+ case p7: clr0 = (1UL << 7); break;
+ case p8: clr0 = (1UL << 6); break;
+ case p9: clr0 = (1UL << 0); break;
+ case p10: clr0 = (1UL << 1); break;
+ case p11: clr0 = (1UL << 18); break;
+ case p12: clr0 = (1UL << 17); break;
+ case p13: clr0 = (1UL << 15); break;
+ case p14: clr0 = (1UL << 16); break;
+ case p15: clr0 = (1UL << 23); break;
+ case p16: clr0 = (1UL << 24); break;
+ case p17: clr0 = (1UL << 25); break;
+ case p18: clr0 = (1UL << 26); break;
+ case p21: clr2 = (1UL << 5); break;
+ case p22: clr2 = (1UL << 4); break;
+ case p23: clr2 = (1UL << 3); break;
+ case p24: clr2 = (1UL << 2); break;
+ case p25: clr2 = (1UL << 1); break;
+ case p26: clr2 = (1UL << 0); break;
+ case p27: clr0 = (1UL << 11); break;
+ case p28: clr0 = (1UL << 10); break;
+ case p29: clr0 = (1UL << 5); break;
+ case p30: clr0 = (1UL << 4); break;
+ }
+
+ if (clr0) LPC_GPIOINT->IO0IntClr = clr0;
+ if (clr2) LPC_GPIOINT->IO2IntClr = clr2;
+}
+
+}; // namespace AjK ends