xref: /btstack/port/archive/msp430f5229lp-cc2564b/src/hal_uart_dma.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
11664436fSMatthias Ringwald /*
21664436fSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
31664436fSMatthias Ringwald  *
41664436fSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
51664436fSMatthias Ringwald  * modification, are permitted provided that the following conditions
61664436fSMatthias Ringwald  * are met:
71664436fSMatthias Ringwald  *
81664436fSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
91664436fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
101664436fSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
111664436fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
121664436fSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
131664436fSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
141664436fSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
151664436fSMatthias Ringwald  *    from this software without specific prior written permission.
161664436fSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
171664436fSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
181664436fSMatthias Ringwald  *    monetary gain.
191664436fSMatthias Ringwald  *
201664436fSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
211664436fSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221664436fSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*2fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251664436fSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
261664436fSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
271664436fSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281664436fSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291664436fSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
301664436fSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311664436fSMatthias Ringwald  * SUCH DAMAGE.
321664436fSMatthias Ringwald  *
331664436fSMatthias Ringwald  * Please inquire about commercial licensing options at
341664436fSMatthias Ringwald  * [email protected]
351664436fSMatthias Ringwald  *
361664436fSMatthias Ringwald  */
371664436fSMatthias Ringwald 
381664436fSMatthias Ringwald /**
391664436fSMatthias Ringwald  * @file  hal_bt.c
401664436fSMatthias Ringwald  ***************************************************************************/
411664436fSMatthias Ringwald #include <stdint.h>
421664436fSMatthias Ringwald 
431664436fSMatthias Ringwald #include <msp430.h>
441664436fSMatthias Ringwald #include "hal_compat.h"
451664436fSMatthias Ringwald 
461664436fSMatthias Ringwald #include "hal_uart_dma.h"
471664436fSMatthias Ringwald 
481664436fSMatthias Ringwald extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
491664436fSMatthias Ringwald 
501664436fSMatthias Ringwald // debugging only
511664436fSMatthias Ringwald // #include <stdio.h>
521664436fSMatthias Ringwald 
531664436fSMatthias Ringwald 
541664436fSMatthias Ringwald // RXD 3.4
551664436fSMatthias Ringwald // TXD 3.3
561664436fSMatthias Ringwald #define BT_PORT_OUT      P3OUT
571664436fSMatthias Ringwald #define BT_PORT_SEL      P3SEL
581664436fSMatthias Ringwald #define BT_PORT_DIR      P3DIR
591664436fSMatthias Ringwald #define BT_PORT_REN      P3REN
601664436fSMatthias Ringwald #define BT_PIN_TXD       BIT3
611664436fSMatthias Ringwald #define BT_PIN_RXD       BIT4
621664436fSMatthias Ringwald 
631664436fSMatthias Ringwald // RTS P2.3
641664436fSMatthias Ringwald #define RTS_SEL P2SEL
651664436fSMatthias Ringwald #define RTS_OUT P2OUT
661664436fSMatthias Ringwald #define RTS_DIR P2DIR
671664436fSMatthias Ringwald #define RTS_PIN BIT3
681664436fSMatthias Ringwald 
691664436fSMatthias Ringwald // CTS P8.1 rewired to P2.6 - only P1 & P2 have interrupts
701664436fSMatthias Ringwald #define CTS_SEL P2SEL
711664436fSMatthias Ringwald #define CTS_OUT P2OUT
721664436fSMatthias Ringwald #define CTS_DIR P2DIR
731664436fSMatthias Ringwald #define CTS_PIN BIT6
741664436fSMatthias Ringwald 
751664436fSMatthias Ringwald // N_SHUTDOWN P4.1
761664436fSMatthias Ringwald #define N_SHUTDOWN_SEL P4SEL
771664436fSMatthias Ringwald #define N_SHUTDOWN_OUT P4OUT
781664436fSMatthias Ringwald #define N_SHUTDOWN_DIR P4DIR
791664436fSMatthias Ringwald #define N_SHUTDOWN_PIN BIT1
801664436fSMatthias Ringwald 
dummy_handler(void)811664436fSMatthias Ringwald void dummy_handler(void){};
821664436fSMatthias Ringwald 
831664436fSMatthias Ringwald // rx state
841664436fSMatthias Ringwald static uint16_t  bytes_to_read = 0;
851664436fSMatthias Ringwald static uint8_t * rx_buffer_ptr = 0;
861664436fSMatthias Ringwald 
871664436fSMatthias Ringwald // tx state
881664436fSMatthias Ringwald static uint16_t  bytes_to_write = 0;
891664436fSMatthias Ringwald static uint8_t * tx_buffer_ptr = 0;
901664436fSMatthias Ringwald 
911664436fSMatthias Ringwald // handlers
921664436fSMatthias Ringwald static void (*rx_done_handler)(void) = dummy_handler;
931664436fSMatthias Ringwald static void (*tx_done_handler)(void) = dummy_handler;
941664436fSMatthias Ringwald static void (*cts_irq_handler)(void) = dummy_handler;
951664436fSMatthias Ringwald 
961664436fSMatthias Ringwald /**
971664436fSMatthias Ringwald  * @brief  Initializes the serial communications peripheral and GPIO ports
981664436fSMatthias Ringwald  *         to communicate with the PAN BT .. assuming 16 Mhz CPU
991664436fSMatthias Ringwald  *
1001664436fSMatthias Ringwald  * @param  none
1011664436fSMatthias Ringwald  *
1021664436fSMatthias Ringwald  * @return none
1031664436fSMatthias Ringwald  */
hal_uart_dma_init(void)1041664436fSMatthias Ringwald void hal_uart_dma_init(void)
1051664436fSMatthias Ringwald {
1061664436fSMatthias Ringwald     BT_PORT_SEL |= BT_PIN_RXD + BT_PIN_TXD;
1071664436fSMatthias Ringwald     BT_PORT_DIR |= BT_PIN_TXD;
1081664436fSMatthias Ringwald     BT_PORT_DIR &= ~BT_PIN_RXD;
1091664436fSMatthias Ringwald 
1101664436fSMatthias Ringwald     // set BT RTS
1111664436fSMatthias Ringwald     RTS_SEL &= ~RTS_PIN;  // = 0 - I/O
1121664436fSMatthias Ringwald     RTS_DIR |=  RTS_PIN;  // = 1 - Output
1131664436fSMatthias Ringwald     RTS_OUT |=  RTS_PIN;  // = 1 - RTS high -> stop
1141664436fSMatthias Ringwald 
1151664436fSMatthias Ringwald     // set BT CTS
1161664436fSMatthias Ringwald     CTS_SEL &= ~CTS_PIN;  // = 0 - I/O
1171664436fSMatthias Ringwald     CTS_DIR &= ~CTS_PIN;  // = 0 - Input
1181664436fSMatthias Ringwald 
1191664436fSMatthias Ringwald     // set BT SHUTDOWN to 1 (active low)
1201664436fSMatthias Ringwald     N_SHUTDOWN_SEL &= ~N_SHUTDOWN_PIN;  // = 0 - I/O
1211664436fSMatthias Ringwald     N_SHUTDOWN_DIR |=  N_SHUTDOWN_PIN;  // = 1 - Output
1221664436fSMatthias Ringwald     N_SHUTDOWN_OUT |=  N_SHUTDOWN_PIN;  // = 1 - Active low -> ok
1231664436fSMatthias Ringwald 
1241664436fSMatthias Ringwald     // wait for Bluetooth to power up properly after providing 32khz clock
1251664436fSMatthias Ringwald     waitAboutOneSecond();
1261664436fSMatthias Ringwald 
1271664436fSMatthias Ringwald     UCA0CTL1 |= UCSWRST;              //Reset State
1281664436fSMatthias Ringwald     UCA0CTL0 = UCMODE_0;
1291664436fSMatthias Ringwald 
1301664436fSMatthias Ringwald     UCA0CTL0 &= ~UC7BIT;              // 8bit char
1311664436fSMatthias Ringwald     UCA0CTL1 |= UCSSEL_2;
1321664436fSMatthias Ringwald 
1331664436fSMatthias Ringwald     UCA0CTL1 &= ~UCSWRST;             // continue
1341664436fSMatthias Ringwald 
1351664436fSMatthias Ringwald     hal_uart_dma_set_baud(115200);
1361664436fSMatthias Ringwald }
1371664436fSMatthias Ringwald 
1381664436fSMatthias Ringwald /**
1391664436fSMatthias Ringwald 
1401664436fSMatthias Ringwald  UART used in low-frequency mode
1411664436fSMatthias Ringwald  In this mode, the maximum USCI baud rate is one-third the UART source clock frequency BRCLK.
1421664436fSMatthias Ringwald 
1431664436fSMatthias Ringwald  16000000 /  576000 = 277.77
1441664436fSMatthias Ringwald  16000000 /  115200 = 138.88
1451664436fSMatthias Ringwald  16000000 /  921600 =  17.36
1461664436fSMatthias Ringwald  16000000 / 1000000 =  16.00
1471664436fSMatthias Ringwald  16000000 / 2000000 =   8.00
1481664436fSMatthias Ringwald  16000000 / 2400000 =   6.66
1491664436fSMatthias Ringwald  16000000 / 3000000 =   3.33
1501664436fSMatthias Ringwald  16000000 / 4000000 =   2.00
1511664436fSMatthias Ringwald 
1521664436fSMatthias Ringwald  */
hal_uart_dma_set_baud(uint32_t baud)1531664436fSMatthias Ringwald int hal_uart_dma_set_baud(uint32_t baud){
1541664436fSMatthias Ringwald 
1551664436fSMatthias Ringwald     int result = 0;
1561664436fSMatthias Ringwald 
1571664436fSMatthias Ringwald     UCA0CTL1 |= UCSWRST;              //Reset State
1581664436fSMatthias Ringwald 
1591664436fSMatthias Ringwald     switch (baud){
1601664436fSMatthias Ringwald 
1611664436fSMatthias Ringwald         case 4000000:
1621664436fSMatthias Ringwald             UCA0BR0 = 2;
1631664436fSMatthias Ringwald             UCA0BR1 = 0;
1641664436fSMatthias Ringwald             UCA0MCTL= 0 << 1;  // + 0.000
1651664436fSMatthias Ringwald             break;
1661664436fSMatthias Ringwald 
1671664436fSMatthias Ringwald         case 3000000:
1681664436fSMatthias Ringwald             UCA0BR0 = 3;
1691664436fSMatthias Ringwald             UCA0BR1 = 0;
1701664436fSMatthias Ringwald             UCA0MCTL= 3 << 1;  // + 0.375
1711664436fSMatthias Ringwald             break;
1721664436fSMatthias Ringwald 
1731664436fSMatthias Ringwald         case 2400000:
1741664436fSMatthias Ringwald             UCA0BR0 = 6;
1751664436fSMatthias Ringwald             UCA0BR1 = 0;
1761664436fSMatthias Ringwald             UCA0MCTL= 5 << 1;  // + 0.625
1771664436fSMatthias Ringwald             break;
1781664436fSMatthias Ringwald 
1791664436fSMatthias Ringwald         case 2000000:
1801664436fSMatthias Ringwald             UCA0BR0 = 8;
1811664436fSMatthias Ringwald             UCA0BR1 = 0;
1821664436fSMatthias Ringwald             UCA0MCTL= 0 << 1;  // + 0.000
1831664436fSMatthias Ringwald             break;
1841664436fSMatthias Ringwald 
1851664436fSMatthias Ringwald         case 1000000:
1861664436fSMatthias Ringwald             UCA0BR0 = 16;
1871664436fSMatthias Ringwald             UCA0BR1 = 0;
1881664436fSMatthias Ringwald             UCA0MCTL= 0 << 1;  // + 0.000
1891664436fSMatthias Ringwald             break;
1901664436fSMatthias Ringwald 
1911664436fSMatthias Ringwald         case 921600:
1921664436fSMatthias Ringwald             UCA0BR0 = 17;
1931664436fSMatthias Ringwald             UCA0BR1 = 0;
1941664436fSMatthias Ringwald             UCA0MCTL= 7 << 1;  // 3 << 1;  // + 0.375
1951664436fSMatthias Ringwald             break;
1961664436fSMatthias Ringwald 
1971664436fSMatthias Ringwald         case 115200:
1981664436fSMatthias Ringwald             UCA0BR0 = 138;  // from family user guide
1991664436fSMatthias Ringwald             UCA0BR1 = 0;
2001664436fSMatthias Ringwald             UCA0MCTL= 7 << 1;  // + 0.875
2011664436fSMatthias Ringwald             break;
2021664436fSMatthias Ringwald 
2031664436fSMatthias Ringwald         case 57600:
2041664436fSMatthias Ringwald             UCA0BR0 = 21;
2051664436fSMatthias Ringwald             UCA0BR1 = 1;
2061664436fSMatthias Ringwald             UCA0MCTL= 7 << 1;  // + 0.875
2071664436fSMatthias Ringwald             break;
2081664436fSMatthias Ringwald 
2091664436fSMatthias Ringwald         default:
2101664436fSMatthias Ringwald             result = -1;
2111664436fSMatthias Ringwald             break;
2121664436fSMatthias Ringwald     }
2131664436fSMatthias Ringwald 
2141664436fSMatthias Ringwald     UCA0CTL1 &= ~UCSWRST;             // continue
2151664436fSMatthias Ringwald 
2161664436fSMatthias Ringwald     return result;
2171664436fSMatthias Ringwald }
2181664436fSMatthias Ringwald 
hal_uart_dma_set_block_received(void (* the_block_handler)(void))2191664436fSMatthias Ringwald void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
2201664436fSMatthias Ringwald     rx_done_handler = the_block_handler;
2211664436fSMatthias Ringwald }
2221664436fSMatthias Ringwald 
hal_uart_dma_set_block_sent(void (* the_block_handler)(void))2231664436fSMatthias Ringwald void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
2241664436fSMatthias Ringwald     tx_done_handler = the_block_handler;
2251664436fSMatthias Ringwald }
2261664436fSMatthias Ringwald 
hal_uart_dma_set_csr_irq_handler(void (* the_irq_handler)(void))2271664436fSMatthias Ringwald void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
2281664436fSMatthias Ringwald #ifdef HAVE_CTS_IRQ
2291664436fSMatthias Ringwald     if (the_irq_handler){
2301664436fSMatthias Ringwald         P2IFG  =  0;     // no IRQ pending
2311664436fSMatthias Ringwald         P2IV   =  0;     // no IRQ pending
2321664436fSMatthias Ringwald         P2IES &= ~ CTS_PIN;  // IRQ on 0->1 transition
2331664436fSMatthias Ringwald         P2IE  |=   CTS_PIN;  // enable IRQ for P8.1
2341664436fSMatthias Ringwald         cts_irq_handler = the_irq_handler;
2351664436fSMatthias Ringwald         return;
2361664436fSMatthias Ringwald     }
2371664436fSMatthias Ringwald     P2IE  &= ~CTS_PIN;
2381664436fSMatthias Ringwald     cts_irq_handler = dummy_handler;
2391664436fSMatthias Ringwald #endif
2401664436fSMatthias Ringwald }
2411664436fSMatthias Ringwald 
2421664436fSMatthias Ringwald /**********************************************************************/
2431664436fSMatthias Ringwald /**
2441664436fSMatthias Ringwald  * @brief  Disables the serial communications peripheral and clears the GPIO
2451664436fSMatthias Ringwald  *         settings used to communicate with the BT.
2461664436fSMatthias Ringwald  *
2471664436fSMatthias Ringwald  * @param  none
2481664436fSMatthias Ringwald  *
2491664436fSMatthias Ringwald  * @return none
2501664436fSMatthias Ringwald  **************************************************************************/
hal_uart_dma_shutdown(void)2511664436fSMatthias Ringwald void hal_uart_dma_shutdown(void) {
2521664436fSMatthias Ringwald 
2531664436fSMatthias Ringwald     UCA0IE &= ~(UCRXIE | UCTXIE);
2541664436fSMatthias Ringwald     UCA0CTL1 = UCSWRST;                          //Reset State
2551664436fSMatthias Ringwald     BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD );
2561664436fSMatthias Ringwald     BT_PORT_DIR |= BT_PIN_TXD;
2571664436fSMatthias Ringwald     BT_PORT_DIR |= BT_PIN_RXD;
2581664436fSMatthias Ringwald     BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD);
2591664436fSMatthias Ringwald }
2601664436fSMatthias Ringwald 
hal_uart_dma_send_block(const uint8_t * data,uint16_t len)2611664436fSMatthias Ringwald void hal_uart_dma_send_block(const uint8_t * data, uint16_t len){
2621664436fSMatthias Ringwald 
2631664436fSMatthias Ringwald     // printf("hal_uart_dma_send_block, size %u\n\r", len);
2641664436fSMatthias Ringwald 
2651664436fSMatthias Ringwald     UCA0IE &= ~UCTXIE ;  // disable TX interrupts
2661664436fSMatthias Ringwald 
2671664436fSMatthias Ringwald     tx_buffer_ptr = (uint8_t *) data;
2681664436fSMatthias Ringwald     bytes_to_write = len;
2691664436fSMatthias Ringwald 
2701664436fSMatthias Ringwald     UCA0IE |= UCTXIE;    // enable TX interrupts
2711664436fSMatthias Ringwald }
2721664436fSMatthias Ringwald 
hal_uart_dma_enable_rx(void)2731664436fSMatthias Ringwald static inline void hal_uart_dma_enable_rx(void){
2741664436fSMatthias Ringwald     RTS_OUT &= ~ RTS_PIN;  // = 0 - RTS low -> ok
2751664436fSMatthias Ringwald }
2761664436fSMatthias Ringwald 
hal_uart_dma_disable_rx(void)2771664436fSMatthias Ringwald static inline void hal_uart_dma_disable_rx(void){
2781664436fSMatthias Ringwald     RTS_OUT |= RTS_PIN;  // = 1 - RTS high -> stop
2791664436fSMatthias Ringwald }
2801664436fSMatthias Ringwald 
hal_uart_dma_receive_block(uint8_t * buffer,uint16_t len)2811664436fSMatthias Ringwald void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
2821664436fSMatthias Ringwald     // disable RX interrupts
2831664436fSMatthias Ringwald     UCA0IE &= ~UCRXIE;
2841664436fSMatthias Ringwald 
2851664436fSMatthias Ringwald     rx_buffer_ptr = buffer;
2861664436fSMatthias Ringwald     bytes_to_read = len;
2871664436fSMatthias Ringwald 
2881664436fSMatthias Ringwald     // check if byte already received
2891664436fSMatthias Ringwald     int pending = UCA0IFG & UCRXIFG;
2901664436fSMatthias Ringwald 
2911664436fSMatthias Ringwald     // enable RX interrupts - will trigger ISR below if byte pending
2921664436fSMatthias Ringwald     UCA0IE |= UCRXIE;    // enable RX interrupts
2931664436fSMatthias Ringwald 
2941664436fSMatthias Ringwald     // if byte was pending, ISR controls RTS
2951664436fSMatthias Ringwald     if (!pending) {
2961664436fSMatthias Ringwald         hal_uart_dma_enable_rx();
2971664436fSMatthias Ringwald     }
2981664436fSMatthias Ringwald }
2991664436fSMatthias Ringwald 
hal_uart_dma_set_sleep(uint8_t sleep)3001664436fSMatthias Ringwald void hal_uart_dma_set_sleep(uint8_t sleep){
3011664436fSMatthias Ringwald     hal_cpu_set_uart_needed_during_sleep(!sleep);
3021664436fSMatthias Ringwald }
3031664436fSMatthias Ringwald 
3041664436fSMatthias Ringwald // block-wise "DMA" RX/TX UART driver
3051664436fSMatthias Ringwald #ifdef __GNUC__
3061664436fSMatthias Ringwald __attribute__((interrupt(USCI_A0_VECTOR)))
3071664436fSMatthias Ringwald #endif
3081664436fSMatthias Ringwald #ifdef __IAR_SYSTEMS_ICC__
3091664436fSMatthias Ringwald #pragma vector=USCI_A0_VECTOR
3101664436fSMatthias Ringwald __interrupt
3111664436fSMatthias Ringwald #endif
usbRxTxISR(void)3121664436fSMatthias Ringwald void usbRxTxISR(void){
3131664436fSMatthias Ringwald 
3141664436fSMatthias Ringwald     // find reason
3151664436fSMatthias Ringwald     switch (UCA0IV){
3161664436fSMatthias Ringwald 
3171664436fSMatthias Ringwald         case 2: // RXIFG
3181664436fSMatthias Ringwald             if (bytes_to_read == 0) {
3191664436fSMatthias Ringwald                 hal_uart_dma_disable_rx();
3201664436fSMatthias Ringwald                 UCA0IE &= ~UCRXIE ;  // disable RX interrupts
3211664436fSMatthias Ringwald                 return;
3221664436fSMatthias Ringwald             }
3231664436fSMatthias Ringwald             *rx_buffer_ptr = UCA0RXBUF;
3241664436fSMatthias Ringwald             ++rx_buffer_ptr;
3251664436fSMatthias Ringwald             --bytes_to_read;
3261664436fSMatthias Ringwald             if (bytes_to_read > 0) {
3271664436fSMatthias Ringwald                 hal_uart_dma_enable_rx();
3281664436fSMatthias Ringwald                 return;
3291664436fSMatthias Ringwald             }
3301664436fSMatthias Ringwald             RTS_OUT |= RTS_PIN;      // = 1 - RTS high -> stop
3311664436fSMatthias Ringwald             UCA0IE &= ~UCRXIE ; // disable RX interrupts
3321664436fSMatthias Ringwald 
3331664436fSMatthias Ringwald             (*rx_done_handler)();
3341664436fSMatthias Ringwald 
3351664436fSMatthias Ringwald             // force exit low power mode
3361664436fSMatthias Ringwald             __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
3371664436fSMatthias Ringwald 
3381664436fSMatthias Ringwald             break;
3391664436fSMatthias Ringwald 
3401664436fSMatthias Ringwald         case 4: // TXIFG
3411664436fSMatthias Ringwald             if (bytes_to_write == 0){
3421664436fSMatthias Ringwald                 UCA0IE &= ~UCTXIE ;  // disable TX interrupts
3431664436fSMatthias Ringwald                 return;
3441664436fSMatthias Ringwald             }
3451664436fSMatthias Ringwald             UCA0TXBUF = *tx_buffer_ptr;
3461664436fSMatthias Ringwald             ++tx_buffer_ptr;
3471664436fSMatthias Ringwald             --bytes_to_write;
3481664436fSMatthias Ringwald 
3491664436fSMatthias Ringwald             if (bytes_to_write > 0) {
3501664436fSMatthias Ringwald                 return;
3511664436fSMatthias Ringwald             }
3521664436fSMatthias Ringwald 
3531664436fSMatthias Ringwald             UCA0IE &= ~UCTXIE ;  // disable TX interrupts
3541664436fSMatthias Ringwald 
3551664436fSMatthias Ringwald             (*tx_done_handler)();
3561664436fSMatthias Ringwald 
3571664436fSMatthias Ringwald             // force exit low power mode
3581664436fSMatthias Ringwald             __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
3591664436fSMatthias Ringwald 
3601664436fSMatthias Ringwald             break;
3611664436fSMatthias Ringwald 
3621664436fSMatthias Ringwald         default:
3631664436fSMatthias Ringwald             break;
3641664436fSMatthias Ringwald     }
3651664436fSMatthias Ringwald }
3661664436fSMatthias Ringwald 
3671664436fSMatthias Ringwald 
3681664436fSMatthias Ringwald // CTS ISR
3691664436fSMatthias Ringwald #ifdef HAVE_CTS_IRQ
3701664436fSMatthias Ringwald // TODO: there's no PORT8_VECTOR, but configuration seems possible
3711664436fSMatthias Ringwald 
3721664436fSMatthias Ringwald extern void ehcill_handle(uint8_t action);
3731664436fSMatthias Ringwald #define EHCILL_CTS_SIGNAL      0x034
3741664436fSMatthias Ringwald 
3751664436fSMatthias Ringwald #ifdef __GNUC__
3761664436fSMatthias Ringwald __attribute__((interrupt(PORT2_VECTOR)))
3771664436fSMatthias Ringwald #elif defined( __IAR_SYSTEMS_ICC__)
3781664436fSMatthias Ringwald #pragma vector=PORT2_VECTOR
3791664436fSMatthias Ringwald __interrupt
3801664436fSMatthias Ringwald #endif
ctsISR(void)3811664436fSMatthias Ringwald void ctsISR(void){
3821664436fSMatthias Ringwald     P2IV = 0;
3831664436fSMatthias Ringwald     (*cts_irq_handler)();
3841664436fSMatthias Ringwald }
3851664436fSMatthias Ringwald #endif
3861664436fSMatthias Ringwald 
387