<commit_before>/**
 * Copyright (c) 2008-2012 the MansOS team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of  conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//
// msp430x16x USART
//

#define USE_USART_RX 1 // XXX

#include <hil/gpio.h>
#include <hil/usart.h>
#include <hil/spi.h>
#include <kernel/defines.h>
#include "msp430_timers.h"
#include <kernel/threads/threads.h>

//===========================================================
// Data types and constants
//===========================================================

enum Msp430USARTMode_e {
    UM_DISABLED,
    UM_UART,
    UM_SPI_MASTER,
    UM_SPI_SLAVE,
    UM_I2C
} PACKED;

typedef enum Msp430USARTMode_e Msp430USARTMode_t;

USARTCallback_t usartRecvCb[USART_COUNT];

bool usartBusy[USART_COUNT];

#define NOT_IMPLEMENTED -1

//===========================================================
// Procedures
//===========================================================

//-----------------------------------------------------------
//-----------------------------------------------------------

// pointers to USARTx registers:
// TODO - change these to base + offset (base = UART0 reg, offset = 8 * id)
static volatile uint8_t * const UxCTL[USART_COUNT] = { &(U0CTL), &(U1CTL) };
static volatile uint8_t * const UxTCTL[USART_COUNT] = { &(U0TCTL), &(U1TCTL) };
static volatile uint8_t * const UxMCTL[USART_COUNT] = { &(U0MCTL), &(U1MCTL) };
static volatile uint8_t * const UxBR0[USART_COUNT] = { &(U0BR0), &(U1BR0) };
static volatile uint8_t * const UxBR1[USART_COUNT] = { &(U0BR1), &(U1BR1) };
static volatile uint8_t * const UxME[USART_COUNT] = { &(U0ME), &(U1ME) };

// buffers are not static, as they are declared in .h file
volatile uint8_t * const UxTXBUF[USART_COUNT] = { &(U0TXBUF), &(U1TXBUF) };
volatile const uint8_t * const UxRXBUF[USART_COUNT] = { &(U0RXBUF), &(U1RXBUF) };

static volatile uint8_t * const IEx[USART_COUNT] = { &(IE1), &(IE2) };
static volatile uint8_t * const IFGx[USART_COUNT] = { &(IFG1), &(IFG2) };

// USART flags
static const uint8_t USPIEx[USART_COUNT] = { USPIE0, USPIE1 };
static const uint8_t UTXEx[USART_COUNT] = { UTXE0, UTXE1 };
static const uint8_t URXEx[USART_COUNT] = { URXE0, URXE1 };
static const uint8_t URXIEx[USART_COUNT] = { URXIE0, URXIE1 };
static const uint8_t UTXIEx[USART_COUNT] = { UTXIE0, UTXIE1 };
static const uint8_t UTXIFGx[USART_COUNT] = { UTXIFG0, UTXIFG1 };
static const uint8_t URXIFGx[USART_COUNT] = { URXIFG0, URXIFG1 };

// actual USARTx mode (UART/SPI/I2C)
static Msp430USARTMode_t usartMode[USART_COUNT] = { UM_DISABLED, UM_DISABLED };


static inline void USARTInitPins(uint8_t id) {
    // Setting port directions & selections for RX/TX
    // cannot use params in macros
    if (id == 0) {
        // USART0
        pinAsOutput(UTXD0_PORT, UTXD0_PIN);
        pinAsInput(URXD0_PORT, URXD0_PIN);
        pinClear(UTXD0_PORT, UTXD0_PIN);
        pinAsFunction(UTXD0_PORT, UTXD0_PIN);
        pinAsFunction(URXD0_PORT, URXD0_PIN);
    } else if (id == 1) {
        // USART 1
        pinAsOutput(UTXD1_PORT, UTXD1_PIN);
        pinAsInput(URXD1_PORT, URXD1_PIN);
        pinClear(UTXD1_PORT, UTXD1_PIN);
        pinAsFunction(UTXD1_PORT, UTXD1_PIN);
        pinAsFunction(URXD1_PORT, URXD1_PIN);
    }
}

static inline void USARTInitSpeed(uint8_t id, uint32_t speed) {
    uint8_t clock;
    uint8_t frequency;
    uint8_t correction;

    // The values were calculated using baudrate calculator:
    // http://mspgcc.sourceforge.net/baudrate.html
    // basically: BR0 ~= CLOCK_FREQUENCY / BAUDRATE, and MCTL is correction value
    switch(speed) {
    case 4800:
        clock = SSEL_ACLK; // use ACLK
        frequency = 0x6;
        correction = 0x77;
        break; 

    default:
        // TODO: Tell somehow, that no valid speed is selected/found,
        // but use 9600 for now
    case 9600:
        clock = SSEL_ACLK; // use ACLK, assuming 32khz
#if ACLK_SPEED == 32768
        // assume 32'768 Hz crystal
        frequency = 0x3;
        correction = 0x29;
#else
        // assume 32'000 Hz crystal
        frequency = 0x3;
        correction = 0x4C;
#endif
        break;

    case 38400:
        clock = SSEL_SMCLK;    // use SMCLK<commit_msg>+) added support for MSP430 UART 2400 baudrate<commit_after>/**
 * Copyright (c) 2008-2012 the MansOS team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of  conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//
// msp430x16x USART
//

#define USE_USART_RX 1 // XXX

#include <hil/gpio.h>
#include <hil/usart.h>
#include <hil/spi.h>
#include <kernel/defines.h>
#include "msp430_timers.h"
#include <kernel/threads/threads.h>

//===========================================================
// Data types and constants
//===========================================================

enum Msp430USARTMode_e {
    UM_DISABLED,
    UM_UART,
    UM_SPI_MASTER,
    UM_SPI_SLAVE,
    UM_I2C
} PACKED;

typedef enum Msp430USARTMode_e Msp430USARTMode_t;

USARTCallback_t usartRecvCb[USART_COUNT];

bool usartBusy[USART_COUNT];

#define NOT_IMPLEMENTED -1

//===========================================================
// Procedures
//===========================================================

//-----------------------------------------------------------
//-----------------------------------------------------------

// pointers to USARTx registers:
// TODO - change these to base + offset (base = UART0 reg, offset = 8 * id)
static volatile uint8_t * const UxCTL[USART_COUNT] = { &(U0CTL), &(U1CTL) };
static volatile uint8_t * const UxTCTL[USART_COUNT] = { &(U0TCTL), &(U1TCTL) };
static volatile uint8_t * const UxMCTL[USART_COUNT] = { &(U0MCTL), &(U1MCTL) };
static volatile uint8_t * const UxBR0[USART_COUNT] = { &(U0BR0), &(U1BR0) };
static volatile uint8_t * const UxBR1[USART_COUNT] = { &(U0BR1), &(U1BR1) };
static volatile uint8_t * const UxME[USART_COUNT] = { &(U0ME), &(U1ME) };

// buffers are not static, as they are declared in .h file
volatile uint8_t * const UxTXBUF[USART_COUNT] = { &(U0TXBUF), &(U1TXBUF) };
volatile const uint8_t * const UxRXBUF[USART_COUNT] = { &(U0RXBUF), &(U1RXBUF) };

static volatile uint8_t * const IEx[USART_COUNT] = { &(IE1), &(IE2) };
static volatile uint8_t * const IFGx[USART_COUNT] = { &(IFG1), &(IFG2) };

// USART flags
static const uint8_t USPIEx[USART_COUNT] = { USPIE0, USPIE1 };
static const uint8_t UTXEx[USART_COUNT] = { UTXE0, UTXE1 };
static const uint8_t URXEx[USART_COUNT] = { URXE0, URXE1 };
static const uint8_t URXIEx[USART_COUNT] = { URXIE0, URXIE1 };
static const uint8_t UTXIEx[USART_COUNT] = { UTXIE0, UTXIE1 };
static const uint8_t UTXIFGx[USART_COUNT] = { UTXIFG0, UTXIFG1 };
static const uint8_t URXIFGx[USART_COUNT] = { URXIFG0, URXIFG1 };

// actual USARTx mode (UART/SPI/I2C)
static Msp430USARTMode_t usartMode[USART_COUNT] = { UM_DISABLED, UM_DISABLED };


static inline void USARTInitPins(uint8_t id) {
    // Setting port directions & selections for RX/TX
    // cannot use params in macros
    if (id == 0) {
        // USART0
        pinAsOutput(UTXD0_PORT, UTXD0_PIN);
        pinAsInput(URXD0_PORT, URXD0_PIN);
        pinClear(UTXD0_PORT, UTXD0_PIN);
        pinAsFunction(UTXD0_PORT, UTXD0_PIN);
        pinAsFunction(URXD0_PORT, URXD0_PIN);
    } else if (id == 1) {
        // USART 1
        pinAsOutput(UTXD1_PORT, UTXD1_PIN);
        pinAsInput(URXD1_PORT, URXD1_PIN);
        pinClear(UTXD1_PORT, UTXD1_PIN);
        pinAsFunction(UTXD1_PORT, UTXD1_PIN);
        pinAsFunction(URXD1_PORT, URXD1_PIN);
    }
}

static inline void USARTInitSpeed(uint8_t id, uint32_t speed) {
    uint8_t clock;
    uint8_t frequency;
    uint8_t correction;

    // The values were calculated using baudrate calculator:
    // http://mspgcc.sourceforge.net/baudrate.html
    // basically: BR0 ~= CLOCK_FREQUENCY / BAUDRATE, and MCTL is correction value
    switch(speed) {

    // Added by Girts 2012-05-18 (User's guide page 265)
    case 2400:
        clock = SSEL_ACLK; // use ACLK
        frequency = 0xd;
        correction = 0x6b;
        break; 

    case 4800:
        clock = SSEL_ACLK; // use ACLK
        frequency = 0x6;
        correction = 0x77;
        break;

    default:
        // TODO: Tell somehow, that no valid speed is selected/found,
        // but use 9600 for now
    case 9600:
        clock = SSEL_ACLK; // use ACLK, assuming 32khz
#if ACLK_SPEED == 32768
        // assume 32'768 Hz crystal
        frequency = 0x3;
        correction = 0x29;
#else
        // assume 32'000 Hz crystal
        frequency = 0x3;
        correction = 0x4C;
#endif
        break;

    case 38400:
        clock = SSEL_SMCLK;    // use SMCLK
{'fraction_non_alphanumeric': 0.1567937967721576, 'fraction_numerical': 0.03308989270579749, 'mean_word_length': 3.3092463092463094, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2245986', 'n_tokens_mistral': 3954, 'n_tokens_neox': 3682, 'n_words': 1077}