mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Mon Jul 13 09:45:08 2015 +0100
Revision:
589:6c996abb70b0
Parent:
570:e6ed7264c56c
Synchronized with git revision 3a12b5f998967abbcf8b2884bea8b85b61196753

Full URL: https://github.com/mbedmicro/mbed/commit/3a12b5f998967abbcf8b2884bea8b85b61196753/

I2C PeripheralPins bug fix.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 85:e1a8e879a6a9 1 /* mbed Microcontroller Library
mbed_official 104:a6a92e2e5a92 2 * Copyright (c) 2013 Nordic Semiconductor
mbed_official 85:e1a8e879a6a9 3 *
mbed_official 85:e1a8e879a6a9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 85:e1a8e879a6a9 5 * you may not use this file except in compliance with the License.
mbed_official 85:e1a8e879a6a9 6 * You may obtain a copy of the License at
mbed_official 85:e1a8e879a6a9 7 *
mbed_official 85:e1a8e879a6a9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 85:e1a8e879a6a9 9 *
mbed_official 85:e1a8e879a6a9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 85:e1a8e879a6a9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 85:e1a8e879a6a9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 85:e1a8e879a6a9 13 * See the License for the specific language governing permissions and
mbed_official 85:e1a8e879a6a9 14 * limitations under the License.
mbed_official 85:e1a8e879a6a9 15 */
mbed_official 85:e1a8e879a6a9 16 // math.h required for floating point operations for baud rate calculation
mbed_official 85:e1a8e879a6a9 17 //#include <math.h>
mbed_official 85:e1a8e879a6a9 18 #include <string.h>
mbed_official 227:7bd0639b8911 19 #include "mbed_assert.h"
mbed_official 85:e1a8e879a6a9 20
mbed_official 85:e1a8e879a6a9 21 #include "serial_api.h"
mbed_official 85:e1a8e879a6a9 22 #include "cmsis.h"
mbed_official 85:e1a8e879a6a9 23 #include "pinmap.h"
mbed_official 227:7bd0639b8911 24
mbed_official 85:e1a8e879a6a9 25 /******************************************************************************
mbed_official 85:e1a8e879a6a9 26 * INITIALIZATION
mbed_official 85:e1a8e879a6a9 27 ******************************************************************************/
mbed_official 85:e1a8e879a6a9 28 #define UART_NUM 1
mbed_official 85:e1a8e879a6a9 29
mbed_official 85:e1a8e879a6a9 30 static uint32_t serial_irq_ids[UART_NUM] = {0};
mbed_official 85:e1a8e879a6a9 31 static uart_irq_handler irq_handler;
mbed_official 589:6c996abb70b0 32 static const int acceptedSpeeds[17][2] = {
mbed_official 589:6c996abb70b0 33 {1200, UART_BAUDRATE_BAUDRATE_Baud1200},
mbed_official 589:6c996abb70b0 34 {2400, UART_BAUDRATE_BAUDRATE_Baud2400},
mbed_official 589:6c996abb70b0 35 {4800, UART_BAUDRATE_BAUDRATE_Baud4800},
mbed_official 589:6c996abb70b0 36 {9600, UART_BAUDRATE_BAUDRATE_Baud9600},
mbed_official 589:6c996abb70b0 37 {14400, UART_BAUDRATE_BAUDRATE_Baud14400},
mbed_official 589:6c996abb70b0 38 {19200, UART_BAUDRATE_BAUDRATE_Baud19200},
mbed_official 589:6c996abb70b0 39 {28800, UART_BAUDRATE_BAUDRATE_Baud28800},
mbed_official 589:6c996abb70b0 40 {31250, (0x00800000UL) /* 31250 baud */},
mbed_official 589:6c996abb70b0 41 {38400, UART_BAUDRATE_BAUDRATE_Baud38400},
mbed_official 589:6c996abb70b0 42 {57600, UART_BAUDRATE_BAUDRATE_Baud57600},
mbed_official 589:6c996abb70b0 43 {76800, UART_BAUDRATE_BAUDRATE_Baud76800},
mbed_official 589:6c996abb70b0 44 {115200, UART_BAUDRATE_BAUDRATE_Baud115200},
mbed_official 589:6c996abb70b0 45 {230400, UART_BAUDRATE_BAUDRATE_Baud230400},
mbed_official 589:6c996abb70b0 46 {250000, UART_BAUDRATE_BAUDRATE_Baud250000},
mbed_official 589:6c996abb70b0 47 {460800, UART_BAUDRATE_BAUDRATE_Baud460800},
mbed_official 589:6c996abb70b0 48 {921600, UART_BAUDRATE_BAUDRATE_Baud921600},
mbed_official 589:6c996abb70b0 49 {1000000, UART_BAUDRATE_BAUDRATE_Baud1M}
mbed_official 589:6c996abb70b0 50 };
mbed_official 85:e1a8e879a6a9 51
mbed_official 85:e1a8e879a6a9 52 int stdio_uart_inited = 0;
mbed_official 85:e1a8e879a6a9 53 serial_t stdio_uart;
mbed_official 85:e1a8e879a6a9 54
mbed_official 85:e1a8e879a6a9 55
mbed_official 85:e1a8e879a6a9 56 void serial_init(serial_t *obj, PinName tx, PinName rx) {
mbed_official 288:17565898c031 57 UARTName uart = UART_0;
mbed_official 85:e1a8e879a6a9 58 obj->uart = (NRF_UART_Type *)uart;
mbed_official 300:55638feb26a4 59
mbed_official 227:7bd0639b8911 60 //pin configurations --
mbed_official 300:55638feb26a4 61 NRF_GPIO->DIR |= (1 << tx); //TX_PIN_NUMBER);
mbed_official 300:55638feb26a4 62 NRF_GPIO->DIR |= (1 << RTS_PIN_NUMBER);
mbed_official 85:e1a8e879a6a9 63
mbed_official 300:55638feb26a4 64 NRF_GPIO->DIR &= ~(1 << rx); //RX_PIN_NUMBER);
mbed_official 300:55638feb26a4 65 NRF_GPIO->DIR &= ~(1 << CTS_PIN_NUMBER);
mbed_official 300:55638feb26a4 66
mbed_official 300:55638feb26a4 67
mbed_official 85:e1a8e879a6a9 68 // set default baud rate and format
mbed_official 85:e1a8e879a6a9 69 serial_baud (obj, 9600);
mbed_official 85:e1a8e879a6a9 70 serial_format(obj, 8, ParityNone, 1);
mbed_official 300:55638feb26a4 71
mbed_official 300:55638feb26a4 72 obj->uart->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
mbed_official 85:e1a8e879a6a9 73 obj->uart->TASKS_STARTTX = 1;
mbed_official 85:e1a8e879a6a9 74 obj->uart->TASKS_STARTRX = 1;
mbed_official 300:55638feb26a4 75 obj->uart->EVENTS_RXDRDY = 0;
mbed_official 433:73d4f6083dd2 76 // dummy write needed or TXDRDY trails write rather than leads write.
mbed_official 433:73d4f6083dd2 77 // pins are disconnected so nothing is physically transmitted on the wire
mbed_official 433:73d4f6083dd2 78 obj->uart->TXD = 0;
mbed_official 300:55638feb26a4 79
mbed_official 85:e1a8e879a6a9 80 obj->index = 0;
mbed_official 519:ec58d8604398 81
mbed_official 433:73d4f6083dd2 82 obj->uart->PSELRTS = RTS_PIN_NUMBER;
mbed_official 433:73d4f6083dd2 83 obj->uart->PSELTXD = tx; //TX_PIN_NUMBER;
mbed_official 433:73d4f6083dd2 84 obj->uart->PSELCTS = CTS_PIN_NUMBER;
mbed_official 433:73d4f6083dd2 85 obj->uart->PSELRXD = rx; //RX_PIN_NUMBER;
mbed_official 300:55638feb26a4 86
mbed_official 85:e1a8e879a6a9 87 // set rx/tx pins in PullUp mode
mbed_official 339:40bd4701f3e2 88 if (tx != NC) {
mbed_official 339:40bd4701f3e2 89 pin_mode(tx, PullUp);
mbed_official 339:40bd4701f3e2 90 }
mbed_official 339:40bd4701f3e2 91 if (rx != NC) {
mbed_official 339:40bd4701f3e2 92 pin_mode(rx, PullUp);
mbed_official 339:40bd4701f3e2 93 }
mbed_official 300:55638feb26a4 94
mbed_official 85:e1a8e879a6a9 95 if (uart == STDIO_UART) {
mbed_official 85:e1a8e879a6a9 96 stdio_uart_inited = 1;
mbed_official 85:e1a8e879a6a9 97 memcpy(&stdio_uart, obj, sizeof(serial_t));
mbed_official 85:e1a8e879a6a9 98 }
mbed_official 85:e1a8e879a6a9 99 }
mbed_official 85:e1a8e879a6a9 100
mbed_official 300:55638feb26a4 101 void serial_free(serial_t *obj)
mbed_official 300:55638feb26a4 102 {
mbed_official 85:e1a8e879a6a9 103 serial_irq_ids[obj->index] = 0;
mbed_official 85:e1a8e879a6a9 104 }
mbed_official 85:e1a8e879a6a9 105
mbed_official 85:e1a8e879a6a9 106 // serial_baud
mbed_official 85:e1a8e879a6a9 107 // set the baud rate, taking in to account the current SystemFrequency
mbed_official 300:55638feb26a4 108 void serial_baud(serial_t *obj, int baudrate)
mbed_official 300:55638feb26a4 109 {
mbed_official 300:55638feb26a4 110 if (baudrate<=1200) {
mbed_official 85:e1a8e879a6a9 111 obj->uart->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
mbed_official 85:e1a8e879a6a9 112 return;
mbed_official 227:7bd0639b8911 113 }
mbed_official 300:55638feb26a4 114
mbed_official 407:bbbab616ce8f 115 for (int i = 1; i<17; i++) {
mbed_official 300:55638feb26a4 116 if (baudrate<acceptedSpeeds[i][0]) {
mbed_official 300:55638feb26a4 117 obj->uart->BAUDRATE = acceptedSpeeds[i - 1][1];
mbed_official 85:e1a8e879a6a9 118 return;
mbed_official 85:e1a8e879a6a9 119 }
mbed_official 85:e1a8e879a6a9 120 }
mbed_official 85:e1a8e879a6a9 121 obj->uart->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
mbed_official 85:e1a8e879a6a9 122 }
mbed_official 85:e1a8e879a6a9 123
mbed_official 300:55638feb26a4 124 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
mbed_official 300:55638feb26a4 125 {
mbed_official 85:e1a8e879a6a9 126 // 0: 1 stop bits, 1: 2 stop bits
mbed_official 300:55638feb26a4 127 // int parity_enable, parity_select;
mbed_official 85:e1a8e879a6a9 128 switch (parity) {
mbed_official 227:7bd0639b8911 129 case ParityNone:
mbed_official 300:55638feb26a4 130 obj->uart->CONFIG = 0;
mbed_official 300:55638feb26a4 131 break;
mbed_official 85:e1a8e879a6a9 132 default:
mbed_official 300:55638feb26a4 133 obj->uart->CONFIG = (UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos);
mbed_official 85:e1a8e879a6a9 134 return;
mbed_official 85:e1a8e879a6a9 135 }
mbed_official 85:e1a8e879a6a9 136 //no Flow Control
mbed_official 85:e1a8e879a6a9 137 }
mbed_official 85:e1a8e879a6a9 138
mbed_official 85:e1a8e879a6a9 139 //******************************************************************************
mbed_official 85:e1a8e879a6a9 140 // * INTERRUPT HANDLING
mbed_official 85:e1a8e879a6a9 141 //******************************************************************************
mbed_official 300:55638feb26a4 142 static inline void uart_irq(uint32_t iir, uint32_t index)
mbed_official 300:55638feb26a4 143 {
mbed_official 85:e1a8e879a6a9 144 SerialIrq irq_type;
mbed_official 85:e1a8e879a6a9 145 switch (iir) {
mbed_official 227:7bd0639b8911 146 case 1:
mbed_official 227:7bd0639b8911 147 irq_type = TxIrq;
mbed_official 300:55638feb26a4 148 break;
mbed_official 227:7bd0639b8911 149 case 2:
mbed_official 227:7bd0639b8911 150 irq_type = RxIrq;
mbed_official 300:55638feb26a4 151 break;
mbed_official 300:55638feb26a4 152
mbed_official 300:55638feb26a4 153 default:
mbed_official 300:55638feb26a4 154 return;
mbed_official 85:e1a8e879a6a9 155 }
mbed_official 300:55638feb26a4 156
mbed_official 300:55638feb26a4 157 if (serial_irq_ids[index] != 0) {
mbed_official 85:e1a8e879a6a9 158 irq_handler(serial_irq_ids[index], irq_type);
mbed_official 85:e1a8e879a6a9 159 }
mbed_official 85:e1a8e879a6a9 160 }
mbed_official 300:55638feb26a4 161
mbed_official 85:e1a8e879a6a9 162 #ifdef __cplusplus
mbed_official 85:e1a8e879a6a9 163 extern "C" {
mbed_official 227:7bd0639b8911 164 #endif
mbed_official 85:e1a8e879a6a9 165 void UART0_IRQHandler()
mbed_official 85:e1a8e879a6a9 166 {
mbed_official 519:ec58d8604398 167 uint32_t irtype = 0;
mbed_official 300:55638feb26a4 168
mbed_official 519:ec58d8604398 169 if((NRF_UART0->INTENSET & 0x80) && NRF_UART0->EVENTS_TXDRDY) {
mbed_official 519:ec58d8604398 170 irtype = 1;
mbed_official 519:ec58d8604398 171 } else if((NRF_UART0->INTENSET & 0x04) && NRF_UART0->EVENTS_RXDRDY) {
mbed_official 519:ec58d8604398 172 irtype = 2;
mbed_official 85:e1a8e879a6a9 173 }
mbed_official 519:ec58d8604398 174 uart_irq(irtype, 0);
mbed_official 85:e1a8e879a6a9 175 }
mbed_official 300:55638feb26a4 176
mbed_official 85:e1a8e879a6a9 177 #ifdef __cplusplus
mbed_official 85:e1a8e879a6a9 178 }
mbed_official 227:7bd0639b8911 179 #endif
mbed_official 300:55638feb26a4 180 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
mbed_official 300:55638feb26a4 181 {
mbed_official 300:55638feb26a4 182 irq_handler = handler;
mbed_official 85:e1a8e879a6a9 183 serial_irq_ids[obj->index] = id;
mbed_official 85:e1a8e879a6a9 184 }
mbed_official 85:e1a8e879a6a9 185
mbed_official 300:55638feb26a4 186 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
mbed_official 300:55638feb26a4 187 {
mbed_official 85:e1a8e879a6a9 188 IRQn_Type irq_n = (IRQn_Type)0;
mbed_official 85:e1a8e879a6a9 189
mbed_official 85:e1a8e879a6a9 190 switch ((int)obj->uart) {
mbed_official 300:55638feb26a4 191 case UART_0:
mbed_official 300:55638feb26a4 192 irq_n = UART0_IRQn;
mbed_official 85:e1a8e879a6a9 193 break;
mbed_official 85:e1a8e879a6a9 194 }
mbed_official 300:55638feb26a4 195
mbed_official 85:e1a8e879a6a9 196 if (enable) {
mbed_official 85:e1a8e879a6a9 197 switch (irq) {
mbed_official 300:55638feb26a4 198 case RxIrq:
mbed_official 501:36015dec7d16 199 obj->uart->INTENSET = (UART_INTENSET_RXDRDY_Msk);
mbed_official 300:55638feb26a4 200 break;
mbed_official 300:55638feb26a4 201 case TxIrq:
mbed_official 501:36015dec7d16 202 obj->uart->INTENSET = (UART_INTENSET_TXDRDY_Msk);
mbed_official 300:55638feb26a4 203 break;
mbed_official 85:e1a8e879a6a9 204 }
mbed_official 85:e1a8e879a6a9 205 NVIC_SetPriority(irq_n, 3);
mbed_official 85:e1a8e879a6a9 206 NVIC_EnableIRQ(irq_n);
mbed_official 300:55638feb26a4 207 } else { // disable
mbed_official 433:73d4f6083dd2 208 // maseked writes to INTENSET dont disable and masked writes to
mbed_official 433:73d4f6083dd2 209 // INTENCLR seemed to clear the entire register, not bits.
mbed_official 433:73d4f6083dd2 210 // Added INTEN to memory map and seems to allow set and clearing of specific bits as desired
mbed_official 85:e1a8e879a6a9 211 int all_disabled = 0;
mbed_official 85:e1a8e879a6a9 212 switch (irq) {
mbed_official 300:55638feb26a4 213 case RxIrq:
mbed_official 501:36015dec7d16 214 obj->uart->INTENCLR = (UART_INTENCLR_RXDRDY_Msk);
mbed_official 501:36015dec7d16 215 all_disabled = (obj->uart->INTENCLR & (UART_INTENCLR_TXDRDY_Msk)) == 0;
mbed_official 300:55638feb26a4 216 break;
mbed_official 300:55638feb26a4 217 case TxIrq:
mbed_official 501:36015dec7d16 218 obj->uart->INTENCLR = (UART_INTENCLR_TXDRDY_Msk);
mbed_official 501:36015dec7d16 219 all_disabled = (obj->uart->INTENCLR & (UART_INTENCLR_RXDRDY_Msk)) == 0;
mbed_official 300:55638feb26a4 220 break;
mbed_official 85:e1a8e879a6a9 221 }
mbed_official 300:55638feb26a4 222
mbed_official 300:55638feb26a4 223 if (all_disabled) {
mbed_official 85:e1a8e879a6a9 224 NVIC_DisableIRQ(irq_n);
mbed_official 85:e1a8e879a6a9 225 }
mbed_official 85:e1a8e879a6a9 226 }
mbed_official 85:e1a8e879a6a9 227 }
mbed_official 85:e1a8e879a6a9 228
mbed_official 85:e1a8e879a6a9 229 //******************************************************************************
mbed_official 85:e1a8e879a6a9 230 //* READ/WRITE
mbed_official 85:e1a8e879a6a9 231 //******************************************************************************
mbed_official 300:55638feb26a4 232 int serial_getc(serial_t *obj)
mbed_official 300:55638feb26a4 233 {
mbed_official 300:55638feb26a4 234 while (!serial_readable(obj)) {
mbed_official 300:55638feb26a4 235 }
mbed_official 300:55638feb26a4 236
mbed_official 85:e1a8e879a6a9 237 obj->uart->EVENTS_RXDRDY = 0;
mbed_official 300:55638feb26a4 238
mbed_official 85:e1a8e879a6a9 239 return (uint8_t)obj->uart->RXD;
mbed_official 85:e1a8e879a6a9 240 }
mbed_official 85:e1a8e879a6a9 241
mbed_official 300:55638feb26a4 242 void serial_putc(serial_t *obj, int c)
mbed_official 300:55638feb26a4 243 {
mbed_official 519:ec58d8604398 244 while (!serial_writable(obj)) {
mbed_official 519:ec58d8604398 245 }
mbed_official 300:55638feb26a4 246
mbed_official 519:ec58d8604398 247 obj->uart->EVENTS_TXDRDY = 0;
mbed_official 519:ec58d8604398 248 obj->uart->TXD = (uint8_t)c;
mbed_official 85:e1a8e879a6a9 249 }
mbed_official 85:e1a8e879a6a9 250
mbed_official 300:55638feb26a4 251 int serial_readable(serial_t *obj)
mbed_official 300:55638feb26a4 252 {
mbed_official 85:e1a8e879a6a9 253 return (obj->uart->EVENTS_RXDRDY == 1);
mbed_official 85:e1a8e879a6a9 254 }
mbed_official 85:e1a8e879a6a9 255
mbed_official 300:55638feb26a4 256 int serial_writable(serial_t *obj)
mbed_official 300:55638feb26a4 257 {
mbed_official 433:73d4f6083dd2 258 return (obj->uart->EVENTS_TXDRDY == 1);
mbed_official 85:e1a8e879a6a9 259 }
mbed_official 85:e1a8e879a6a9 260
mbed_official 300:55638feb26a4 261 void serial_break_set(serial_t *obj)
mbed_official 300:55638feb26a4 262 {
mbed_official 85:e1a8e879a6a9 263 obj->uart->TASKS_SUSPEND = 1;
mbed_official 85:e1a8e879a6a9 264 }
mbed_official 85:e1a8e879a6a9 265
mbed_official 300:55638feb26a4 266 void serial_break_clear(serial_t *obj)
mbed_official 300:55638feb26a4 267 {
mbed_official 85:e1a8e879a6a9 268 obj->uart->TASKS_STARTTX = 1;
mbed_official 85:e1a8e879a6a9 269 obj->uart->TASKS_STARTRX = 1;
mbed_official 85:e1a8e879a6a9 270 }
mbed_official 340:28d1f895c6fe 271
mbed_official 340:28d1f895c6fe 272 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
mbed_official 340:28d1f895c6fe 273 {
mbed_official 340:28d1f895c6fe 274
mbed_official 340:28d1f895c6fe 275 if (type == FlowControlRTSCTS || type == FlowControlRTS) {
mbed_official 340:28d1f895c6fe 276 NRF_GPIO->DIR |= (1<<rxflow);
mbed_official 340:28d1f895c6fe 277 pin_mode(rxflow, PullUp);
mbed_official 340:28d1f895c6fe 278 obj->uart->PSELRTS = rxflow;
mbed_official 340:28d1f895c6fe 279
mbed_official 340:28d1f895c6fe 280 obj->uart->CONFIG |= 0x01; // Enable HWFC
mbed_official 340:28d1f895c6fe 281 }
mbed_official 340:28d1f895c6fe 282
mbed_official 340:28d1f895c6fe 283 if (type == FlowControlRTSCTS || type == FlowControlCTS) {
mbed_official 340:28d1f895c6fe 284 NRF_GPIO->DIR &= ~(1<<txflow);
mbed_official 340:28d1f895c6fe 285 pin_mode(txflow, PullUp);
mbed_official 340:28d1f895c6fe 286 obj->uart->PSELCTS = txflow;
mbed_official 340:28d1f895c6fe 287
mbed_official 340:28d1f895c6fe 288 obj->uart->CONFIG |= 0x01; // Enable HWFC;
mbed_official 340:28d1f895c6fe 289 }
mbed_official 340:28d1f895c6fe 290
mbed_official 340:28d1f895c6fe 291 if (type == FlowControlNone) {
mbed_official 340:28d1f895c6fe 292 obj->uart->PSELRTS = 0xFFFFFFFF; // Disable RTS
mbed_official 340:28d1f895c6fe 293 obj->uart->PSELCTS = 0xFFFFFFFF; // Disable CTS
mbed_official 340:28d1f895c6fe 294
mbed_official 340:28d1f895c6fe 295 obj->uart->CONFIG &= ~0x01; // Enable HWFC;
mbed_official 340:28d1f895c6fe 296 }
mbed_official 340:28d1f895c6fe 297 }
mbed_official 340:28d1f895c6fe 298
mbed_official 340:28d1f895c6fe 299 void serial_clear(serial_t *obj) {
mbed_official 340:28d1f895c6fe 300 }