mbed library sources. Supersedes mbed-src. Fixes analogIn and analogOut problems for TARGET_STM32F3. Tested on NUCLEO-F303K8, using 3 analogout and 7 analogin channels simultaneously. Added ability for STM32F334R8 and STM32F303K8 to use all three channels of DAC simultaneously. https://developer.mbed.org/users/StevieWray/code/mbed-dev/ Added ability for TARGET_STM32F3 to use more than one ADC simultaneously. https://developer.mbed.org/questions/67997/NUCLEO-F303K8ADC/

Fork of mbed-dev by mbed official

Committer:
neurofun
Date:
Tue Feb 23 21:59:35 2016 +0000
Revision:
70:b3a5af880266
Parent:
0:9b334a45a8ff
Edited DAC routines to allow for the simultaneous use of three channels from two DACs as seen on the STM32F334R8 and STM32F303K8. Edited ADC routines to allow for the simultaneous use of more than one ADC.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:9b334a45a8ff 1 /* mbed Microcontroller Library
bogdanm 0:9b334a45a8ff 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 0:9b334a45a8ff 3 *
bogdanm 0:9b334a45a8ff 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 0:9b334a45a8ff 5 * you may not use this file except in compliance with the License.
bogdanm 0:9b334a45a8ff 6 * You may obtain a copy of the License at
bogdanm 0:9b334a45a8ff 7 *
bogdanm 0:9b334a45a8ff 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 0:9b334a45a8ff 9 *
bogdanm 0:9b334a45a8ff 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 0:9b334a45a8ff 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 0:9b334a45a8ff 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 0:9b334a45a8ff 13 * See the License for the specific language governing permissions and
bogdanm 0:9b334a45a8ff 14 * limitations under the License.
bogdanm 0:9b334a45a8ff 15 */
bogdanm 0:9b334a45a8ff 16 #ifndef MBED_SERIAL_API_H
bogdanm 0:9b334a45a8ff 17 #define MBED_SERIAL_API_H
bogdanm 0:9b334a45a8ff 18
bogdanm 0:9b334a45a8ff 19 #include "device.h"
bogdanm 0:9b334a45a8ff 20 #include "buffer.h"
bogdanm 0:9b334a45a8ff 21 #include "dma_api.h"
bogdanm 0:9b334a45a8ff 22
bogdanm 0:9b334a45a8ff 23 #if DEVICE_SERIAL
bogdanm 0:9b334a45a8ff 24
bogdanm 0:9b334a45a8ff 25 #define SERIAL_EVENT_TX_SHIFT (2)
bogdanm 0:9b334a45a8ff 26 #define SERIAL_EVENT_RX_SHIFT (8)
bogdanm 0:9b334a45a8ff 27
bogdanm 0:9b334a45a8ff 28 #define SERIAL_EVENT_TX_MASK (0x00FC)
bogdanm 0:9b334a45a8ff 29 #define SERIAL_EVENT_RX_MASK (0x3F00)
bogdanm 0:9b334a45a8ff 30
bogdanm 0:9b334a45a8ff 31 #define SERIAL_EVENT_ERROR (1 << 1)
bogdanm 0:9b334a45a8ff 32
bogdanm 0:9b334a45a8ff 33 /**
bogdanm 0:9b334a45a8ff 34 * @defgroup SerialTXEvents Serial TX Events Macros
bogdanm 0:9b334a45a8ff 35 *
bogdanm 0:9b334a45a8ff 36 * @{
bogdanm 0:9b334a45a8ff 37 */
bogdanm 0:9b334a45a8ff 38 #define SERIAL_EVENT_TX_COMPLETE (1 << (SERIAL_EVENT_TX_SHIFT + 0))
bogdanm 0:9b334a45a8ff 39 #define SERIAL_EVENT_TX_ALL (SERIAL_EVENT_TX_COMPLETE)
bogdanm 0:9b334a45a8ff 40 /**@}*/
bogdanm 0:9b334a45a8ff 41
bogdanm 0:9b334a45a8ff 42 /**
bogdanm 0:9b334a45a8ff 43 * @defgroup SerialRXEvents Serial RX Events Macros
bogdanm 0:9b334a45a8ff 44 *
bogdanm 0:9b334a45a8ff 45 * @{
bogdanm 0:9b334a45a8ff 46 */
bogdanm 0:9b334a45a8ff 47 #define SERIAL_EVENT_RX_COMPLETE (1 << (SERIAL_EVENT_RX_SHIFT + 0))
bogdanm 0:9b334a45a8ff 48 #define SERIAL_EVENT_RX_OVERRUN_ERROR (1 << (SERIAL_EVENT_RX_SHIFT + 1))
bogdanm 0:9b334a45a8ff 49 #define SERIAL_EVENT_RX_FRAMING_ERROR (1 << (SERIAL_EVENT_RX_SHIFT + 2))
bogdanm 0:9b334a45a8ff 50 #define SERIAL_EVENT_RX_PARITY_ERROR (1 << (SERIAL_EVENT_RX_SHIFT + 3))
bogdanm 0:9b334a45a8ff 51 #define SERIAL_EVENT_RX_OVERFLOW (1 << (SERIAL_EVENT_RX_SHIFT + 4))
bogdanm 0:9b334a45a8ff 52 #define SERIAL_EVENT_RX_CHARACTER_MATCH (1 << (SERIAL_EVENT_RX_SHIFT + 5))
bogdanm 0:9b334a45a8ff 53 #define SERIAL_EVENT_RX_ALL (SERIAL_EVENT_RX_OVERFLOW | SERIAL_EVENT_RX_PARITY_ERROR | \
bogdanm 0:9b334a45a8ff 54 SERIAL_EVENT_RX_FRAMING_ERROR | SERIAL_EVENT_RX_OVERRUN_ERROR | \
bogdanm 0:9b334a45a8ff 55 SERIAL_EVENT_RX_COMPLETE | SERIAL_EVENT_RX_CHARACTER_MATCH)
bogdanm 0:9b334a45a8ff 56 /**@}*/
bogdanm 0:9b334a45a8ff 57
bogdanm 0:9b334a45a8ff 58 #define SERIAL_RESERVED_CHAR_MATCH (255)
bogdanm 0:9b334a45a8ff 59
bogdanm 0:9b334a45a8ff 60 typedef enum {
bogdanm 0:9b334a45a8ff 61 ParityNone = 0,
bogdanm 0:9b334a45a8ff 62 ParityOdd = 1,
bogdanm 0:9b334a45a8ff 63 ParityEven = 2,
bogdanm 0:9b334a45a8ff 64 ParityForced1 = 3,
bogdanm 0:9b334a45a8ff 65 ParityForced0 = 4
bogdanm 0:9b334a45a8ff 66 } SerialParity;
bogdanm 0:9b334a45a8ff 67
bogdanm 0:9b334a45a8ff 68 typedef enum {
bogdanm 0:9b334a45a8ff 69 RxIrq,
bogdanm 0:9b334a45a8ff 70 TxIrq
bogdanm 0:9b334a45a8ff 71 } SerialIrq;
bogdanm 0:9b334a45a8ff 72
bogdanm 0:9b334a45a8ff 73 typedef enum {
bogdanm 0:9b334a45a8ff 74 FlowControlNone,
bogdanm 0:9b334a45a8ff 75 FlowControlRTS,
bogdanm 0:9b334a45a8ff 76 FlowControlCTS,
bogdanm 0:9b334a45a8ff 77 FlowControlRTSCTS
bogdanm 0:9b334a45a8ff 78 } FlowControl;
bogdanm 0:9b334a45a8ff 79
bogdanm 0:9b334a45a8ff 80 typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event);
bogdanm 0:9b334a45a8ff 81
bogdanm 0:9b334a45a8ff 82 #if DEVICE_SERIAL_ASYNCH
bogdanm 0:9b334a45a8ff 83 /** Asynch serial hal structure
bogdanm 0:9b334a45a8ff 84 */
bogdanm 0:9b334a45a8ff 85 typedef struct {
bogdanm 0:9b334a45a8ff 86 struct serial_s serial; /**< Target specific serial structure */
bogdanm 0:9b334a45a8ff 87 struct buffer_s tx_buff; /**< Tx buffer */
bogdanm 0:9b334a45a8ff 88 struct buffer_s rx_buff; /**< Rx buffer */
bogdanm 0:9b334a45a8ff 89 uint8_t char_match; /**< Character to be matched */
bogdanm 0:9b334a45a8ff 90 uint8_t char_found; /**< State of the matched character */
bogdanm 0:9b334a45a8ff 91 } serial_t;
bogdanm 0:9b334a45a8ff 92
bogdanm 0:9b334a45a8ff 93 #else
bogdanm 0:9b334a45a8ff 94 /** Non-asynch serial hal structure
bogdanm 0:9b334a45a8ff 95 */
bogdanm 0:9b334a45a8ff 96 typedef struct serial_s serial_t;
bogdanm 0:9b334a45a8ff 97
bogdanm 0:9b334a45a8ff 98 #endif
bogdanm 0:9b334a45a8ff 99
bogdanm 0:9b334a45a8ff 100 #ifdef __cplusplus
bogdanm 0:9b334a45a8ff 101 extern "C" {
bogdanm 0:9b334a45a8ff 102 #endif
bogdanm 0:9b334a45a8ff 103
bogdanm 0:9b334a45a8ff 104 /**
bogdanm 0:9b334a45a8ff 105 * \defgroup GeneralSerial Serial Configuration Functions
bogdanm 0:9b334a45a8ff 106 * @{
bogdanm 0:9b334a45a8ff 107 */
bogdanm 0:9b334a45a8ff 108
bogdanm 0:9b334a45a8ff 109 /** Initialize the serial peripheral. It sets the default parameters for serial
bogdanm 0:9b334a45a8ff 110 * peripheral, and configure its specifieds pins.
bogdanm 0:9b334a45a8ff 111 *
bogdanm 0:9b334a45a8ff 112 * @param obj The serial object
bogdanm 0:9b334a45a8ff 113 * @param tx The TX pin
bogdanm 0:9b334a45a8ff 114 * @param rx The RX pin
bogdanm 0:9b334a45a8ff 115 */
bogdanm 0:9b334a45a8ff 116 void serial_init(serial_t *obj, PinName tx, PinName rx);
bogdanm 0:9b334a45a8ff 117
bogdanm 0:9b334a45a8ff 118 /** Release the serial peripheral, not currently invoked. It requires further
bogdanm 0:9b334a45a8ff 119 * resource management.
bogdanm 0:9b334a45a8ff 120 *
bogdanm 0:9b334a45a8ff 121 * @param obj The serial object
bogdanm 0:9b334a45a8ff 122 */
bogdanm 0:9b334a45a8ff 123 void serial_free(serial_t *obj);
bogdanm 0:9b334a45a8ff 124
bogdanm 0:9b334a45a8ff 125 /** Configure the baud rate
bogdanm 0:9b334a45a8ff 126 *
bogdanm 0:9b334a45a8ff 127 * @param obj The serial object
bogdanm 0:9b334a45a8ff 128 * @param baudrate The baud rate to be configured
bogdanm 0:9b334a45a8ff 129 */
bogdanm 0:9b334a45a8ff 130 void serial_baud(serial_t *obj, int baudrate);
bogdanm 0:9b334a45a8ff 131
bogdanm 0:9b334a45a8ff 132 /** Configure the format. Set the number of bits, parity and the number of stop bits
bogdanm 0:9b334a45a8ff 133 *
bogdanm 0:9b334a45a8ff 134 * @param obj The serial object
bogdanm 0:9b334a45a8ff 135 * @param data_bits The number of data bits
bogdanm 0:9b334a45a8ff 136 * @param parity The parity
bogdanm 0:9b334a45a8ff 137 * @param stop_bits The number of stop bits
bogdanm 0:9b334a45a8ff 138 */
bogdanm 0:9b334a45a8ff 139 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits);
bogdanm 0:9b334a45a8ff 140
bogdanm 0:9b334a45a8ff 141 /** The serial interrupt handler registration.
bogdanm 0:9b334a45a8ff 142 *
bogdanm 0:9b334a45a8ff 143 * @param obj The serial object
bogdanm 0:9b334a45a8ff 144 * @param handler The interrupt handler which will be invoked when interrupt fires.
bogdanm 0:9b334a45a8ff 145 * @param id The SerialBase object
bogdanm 0:9b334a45a8ff 146 */
bogdanm 0:9b334a45a8ff 147 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id);
bogdanm 0:9b334a45a8ff 148
bogdanm 0:9b334a45a8ff 149 /** Configure serial interrupt. This function is used for word-approach
bogdanm 0:9b334a45a8ff 150 *
bogdanm 0:9b334a45a8ff 151 * @param obj The serial object
bogdanm 0:9b334a45a8ff 152 * @param irq The serial IRQ type (RX or TX)
bogdanm 0:9b334a45a8ff 153 * @param enable Set to non-zero to enable events, or zero to disable them
bogdanm 0:9b334a45a8ff 154 */
bogdanm 0:9b334a45a8ff 155 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable);
bogdanm 0:9b334a45a8ff 156
bogdanm 0:9b334a45a8ff 157 /** Get character. This is a blocking call, waiting for a character
bogdanm 0:9b334a45a8ff 158 *
bogdanm 0:9b334a45a8ff 159 * @param obj The serial object
bogdanm 0:9b334a45a8ff 160 */
bogdanm 0:9b334a45a8ff 161 int serial_getc(serial_t *obj);
bogdanm 0:9b334a45a8ff 162
bogdanm 0:9b334a45a8ff 163 /** Put a character. This is a blocking call, waiting for a peripheral to be available
bogdanm 0:9b334a45a8ff 164 * for writing
bogdanm 0:9b334a45a8ff 165 *
bogdanm 0:9b334a45a8ff 166 * @param obj The serial object
bogdanm 0:9b334a45a8ff 167 * @param c The character to be sent
bogdanm 0:9b334a45a8ff 168 */
bogdanm 0:9b334a45a8ff 169 void serial_putc(serial_t *obj, int c);
bogdanm 0:9b334a45a8ff 170
bogdanm 0:9b334a45a8ff 171 /** Check if the serial peripheral is readable
bogdanm 0:9b334a45a8ff 172 *
bogdanm 0:9b334a45a8ff 173 * @param obj The serial object
bogdanm 0:9b334a45a8ff 174 * @return Non-zero value if a character can be read, 0 if nothing to read.
bogdanm 0:9b334a45a8ff 175 */
bogdanm 0:9b334a45a8ff 176 int serial_readable(serial_t *obj);
bogdanm 0:9b334a45a8ff 177
bogdanm 0:9b334a45a8ff 178 /** Check if the serial peripheral is writable
bogdanm 0:9b334a45a8ff 179 *
bogdanm 0:9b334a45a8ff 180 * @param obj The serial object
bogdanm 0:9b334a45a8ff 181 * @return Non-zero value if a character can be written, 0 otherwise.
bogdanm 0:9b334a45a8ff 182 */
bogdanm 0:9b334a45a8ff 183 int serial_writable(serial_t *obj);
bogdanm 0:9b334a45a8ff 184
bogdanm 0:9b334a45a8ff 185 /** Clear the serial peripheral
bogdanm 0:9b334a45a8ff 186 *
bogdanm 0:9b334a45a8ff 187 * @param obj The serial object
bogdanm 0:9b334a45a8ff 188 */
bogdanm 0:9b334a45a8ff 189 void serial_clear(serial_t *obj);
bogdanm 0:9b334a45a8ff 190
bogdanm 0:9b334a45a8ff 191 /** Set the break
bogdanm 0:9b334a45a8ff 192 *
bogdanm 0:9b334a45a8ff 193 * @param obj The serial object
bogdanm 0:9b334a45a8ff 194 */
bogdanm 0:9b334a45a8ff 195 void serial_break_set(serial_t *obj);
bogdanm 0:9b334a45a8ff 196
bogdanm 0:9b334a45a8ff 197 /** Clear the break
bogdanm 0:9b334a45a8ff 198 *
bogdanm 0:9b334a45a8ff 199 * @param obj The serial object
bogdanm 0:9b334a45a8ff 200 */
bogdanm 0:9b334a45a8ff 201 void serial_break_clear(serial_t *obj);
bogdanm 0:9b334a45a8ff 202
bogdanm 0:9b334a45a8ff 203 /** Configure the TX pin for UART function.
bogdanm 0:9b334a45a8ff 204 *
bogdanm 0:9b334a45a8ff 205 * @param tx The pin used for TX
bogdanm 0:9b334a45a8ff 206 */
bogdanm 0:9b334a45a8ff 207 void serial_pinout_tx(PinName tx);
bogdanm 0:9b334a45a8ff 208
bogdanm 0:9b334a45a8ff 209 /** Configure the serial for the flow control. It sets flow control in the hardware
bogdanm 0:9b334a45a8ff 210 * if a serial peripheral supports it, otherwise software emulation is used.
bogdanm 0:9b334a45a8ff 211 *
bogdanm 0:9b334a45a8ff 212 * @param obj The serial object
bogdanm 0:9b334a45a8ff 213 * @param type The type of the flow control. Look at the available FlowControl types.
bogdanm 0:9b334a45a8ff 214 * @param rxflow The tx pin
bogdanm 0:9b334a45a8ff 215 * @param txflow The rx pin
bogdanm 0:9b334a45a8ff 216 */
bogdanm 0:9b334a45a8ff 217 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow);
bogdanm 0:9b334a45a8ff 218
bogdanm 0:9b334a45a8ff 219 #if DEVICE_SERIAL_ASYNCH
bogdanm 0:9b334a45a8ff 220
bogdanm 0:9b334a45a8ff 221 /**@}*/
bogdanm 0:9b334a45a8ff 222
bogdanm 0:9b334a45a8ff 223 /**
bogdanm 0:9b334a45a8ff 224 * \defgroup AsynchSerial Asynchronous Serial Hardware Abstraction Layer
bogdanm 0:9b334a45a8ff 225 * @{
bogdanm 0:9b334a45a8ff 226 */
bogdanm 0:9b334a45a8ff 227
bogdanm 0:9b334a45a8ff 228 /** Begin asynchronous TX transfer. The used buffer is specified in the serial object,
bogdanm 0:9b334a45a8ff 229 * tx_buff
bogdanm 0:9b334a45a8ff 230 *
bogdanm 0:9b334a45a8ff 231 * @param obj The serial object
bogdanm 0:9b334a45a8ff 232 * @param tx The buffer for sending
bogdanm 0:9b334a45a8ff 233 * @param tx_length The number of words to transmit
bogdanm 0:9b334a45a8ff 234 * @param tx_width The bit width of buffer word
bogdanm 0:9b334a45a8ff 235 * @param handler The serial handler
bogdanm 0:9b334a45a8ff 236 * @param event The logical OR of events to be registered
bogdanm 0:9b334a45a8ff 237 * @param hint A suggestion for how to use DMA with this transfer
bogdanm 0:9b334a45a8ff 238 * @return Returns number of data transfered, or 0 otherwise
bogdanm 0:9b334a45a8ff 239 */
bogdanm 0:9b334a45a8ff 240 int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint);
bogdanm 0:9b334a45a8ff 241
bogdanm 0:9b334a45a8ff 242 /** Begin asynchronous RX transfer (enable interrupt for data collecting)
bogdanm 0:9b334a45a8ff 243 * The used buffer is specified in the serial object - rx_buff
bogdanm 0:9b334a45a8ff 244 *
bogdanm 0:9b334a45a8ff 245 * @param obj The serial object
bogdanm 0:9b334a45a8ff 246 * @param rx The buffer for sending
bogdanm 0:9b334a45a8ff 247 * @param rx_length The number of words to transmit
bogdanm 0:9b334a45a8ff 248 * @param rx_width The bit width of buffer word
bogdanm 0:9b334a45a8ff 249 * @param handler The serial handler
bogdanm 0:9b334a45a8ff 250 * @param event The logical OR of events to be registered
bogdanm 0:9b334a45a8ff 251 * @param handler The serial handler
bogdanm 0:9b334a45a8ff 252 * @param char_match A character in range 0-254 to be matched
bogdanm 0:9b334a45a8ff 253 * @param hint A suggestion for how to use DMA with this transfer
bogdanm 0:9b334a45a8ff 254 */
bogdanm 0:9b334a45a8ff 255 void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint);
bogdanm 0:9b334a45a8ff 256
bogdanm 0:9b334a45a8ff 257 /** Attempts to determine if the serial peripheral is already in use for TX
bogdanm 0:9b334a45a8ff 258 *
bogdanm 0:9b334a45a8ff 259 * @param obj The serial object
bogdanm 0:9b334a45a8ff 260 * @return Non-zero if the RX transaction is ongoing, 0 otherwise
bogdanm 0:9b334a45a8ff 261 */
bogdanm 0:9b334a45a8ff 262 uint8_t serial_tx_active(serial_t *obj);
bogdanm 0:9b334a45a8ff 263
bogdanm 0:9b334a45a8ff 264 /** Attempts to determine if the serial peripheral is already in use for RX
bogdanm 0:9b334a45a8ff 265 *
bogdanm 0:9b334a45a8ff 266 * @param obj The serial object
bogdanm 0:9b334a45a8ff 267 * @return Non-zero if the RX transaction is ongoing, 0 otherwise
bogdanm 0:9b334a45a8ff 268 */
bogdanm 0:9b334a45a8ff 269 uint8_t serial_rx_active(serial_t *obj);
bogdanm 0:9b334a45a8ff 270
bogdanm 0:9b334a45a8ff 271 /** The asynchronous TX and RX handler.
bogdanm 0:9b334a45a8ff 272 *
bogdanm 0:9b334a45a8ff 273 * @param obj The serial object
bogdanm 0:9b334a45a8ff 274 * @return Returns event flags if a RX transfer termination condition was met or 0 otherwise
bogdanm 0:9b334a45a8ff 275 */
bogdanm 0:9b334a45a8ff 276 int serial_irq_handler_asynch(serial_t *obj);
bogdanm 0:9b334a45a8ff 277
bogdanm 0:9b334a45a8ff 278 /** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
bogdanm 0:9b334a45a8ff 279 * flush TX hardware buffer if TX FIFO is used
bogdanm 0:9b334a45a8ff 280 *
bogdanm 0:9b334a45a8ff 281 * @param obj The serial object
bogdanm 0:9b334a45a8ff 282 */
bogdanm 0:9b334a45a8ff 283 void serial_tx_abort_asynch(serial_t *obj);
bogdanm 0:9b334a45a8ff 284
bogdanm 0:9b334a45a8ff 285 /** Abort the ongoing RX transaction It disables the enabled interrupt for RX and
bogdanm 0:9b334a45a8ff 286 * flush RX hardware buffer if RX FIFO is used
bogdanm 0:9b334a45a8ff 287 *
bogdanm 0:9b334a45a8ff 288 * @param obj The serial object
bogdanm 0:9b334a45a8ff 289 */
bogdanm 0:9b334a45a8ff 290 void serial_rx_abort_asynch(serial_t *obj);
bogdanm 0:9b334a45a8ff 291
bogdanm 0:9b334a45a8ff 292 /**@}*/
bogdanm 0:9b334a45a8ff 293
bogdanm 0:9b334a45a8ff 294 #endif
bogdanm 0:9b334a45a8ff 295
bogdanm 0:9b334a45a8ff 296 #ifdef __cplusplus
bogdanm 0:9b334a45a8ff 297 }
bogdanm 0:9b334a45a8ff 298 #endif
bogdanm 0:9b334a45a8ff 299
bogdanm 0:9b334a45a8ff 300 #endif
bogdanm 0:9b334a45a8ff 301
bogdanm 0:9b334a45a8ff 302 #endif