/*\r
              LUFA Library\r
-     Copyright (C) Dean Camera, 2010.\r
+     Copyright (C) Dean Camera, 2011.\r
 \r
   dean [at] fourwalledcubicle [dot] com\r
            www.lufa-lib.org\r
 */\r
 \r
 /*\r
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+  Copyright 2011  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
 \r
   Permission to use, copy, modify, distribute, and sell this\r
   software and its documentation for any purpose is hereby granted\r
 */\r
 \r
 /** \file\r
- *  \brief Lightweight ring buffer, for fast insertion/deletion.\r
+ *  \brief Lightweight ring buffer, for fast insertion/deletion of bytes.\r
  *\r
  *  Lightweight ring buffer, for fast insertion/deletion. Multiple buffers can be created of\r
  *  different sizes to suit different needs.\r
  *\r
  *  Note that for each buffer, insertion and removal operations may occur at the same time (via\r
- *  a multithreaded ISR based system) however the same kind of operation (two or more insertions\r
+ *  a multi-threaded ISR based system) however the same kind of operation (two or more insertions\r
  *  or deletions) must not overlap. If there is possibility of two or more of the same kind of\r
- *  operating occuring at the same point in time, atomic (mutex) locking should be used.\r
+ *  operating occurring at the same point in time, atomic (mutex) locking should be used.\r
  */\r
  \r
 /** \ingroup Group_MiscDrivers\r
- *  @defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h\r
+ *  \defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h\r
+ *  \brief Lightweight ring buffer, for fast insertion/deletion of bytes.\r
  *\r
  *  \section Sec_Dependencies Module Source Dependencies\r
  *  The following files must be built with any user project that uses this module:\r
  *  different sizes to suit different needs.\r
  *\r
  *  Note that for each buffer, insertion and removal operations may occur at the same time (via\r
- *  a multithreaded ISR based system) however the same kind of operation (two or more insertions\r
+ *  a multi-threaded ISR based system) however the same kind of operation (two or more insertions\r
  *  or deletions) must not overlap. If there is possibility of two or more of the same kind of\r
- *  operating occuring at the same point in time, atomic (mutex) locking should be used.\r
+ *  operating occurring at the same point in time, atomic (mutex) locking should be used.\r
  *\r
  *  \section Sec_ExampleUsage Example Usage\r
  *  The following snippet is an example of how this module may be used within a typical\r
  *\r
  *  \code\r
  *      // Create the buffer structure and its underlying storage array\r
- *      RingBuff_t Buffer;\r
- *      uint8_t    BufferData[128];\r
+ *      RingBuffer_t Buffer;\r
+ *      uint8_t      BufferData[128];\r
  *\r
- *      // Initialise the buffer with the created storage array\r
+ *      // Initialize the buffer with the created storage array\r
  *      RingBuffer_InitBuffer(&Buffer, BufferData, sizeof(BufferData));\r
  *\r
  *      // Insert some data into the buffer\r
  *  @{\r
  */\r
 \r
-#ifndef __RING_BUFF_H__\r
-#define __RING_BUFF_H__\r
+#ifndef __RING_BUFFER_H__\r
+#define __RING_BUFFER_H__\r
 \r
        /* Includes: */\r
-               #include <util/atomic.h>\r
-               #include <stdint.h>\r
-               #include <stdbool.h>\r
+               #include "../../Common/Common.h"\r
 \r
-               #include <LUFA/Common/Common.h>\r
+       /* Enable C linkage for C++ Compilers: */\r
+               #if defined(__cplusplus)\r
+                       extern "C" {\r
+               #endif\r
 \r
        /* Type Defines: */\r
-               /** Type define for a new ring buffer object. Buffers should be initialized via a call to\r
+               /** \brief Ring Buffer Management Structure.\r
+                *\r
+                *  Type define for a new ring buffer object. Buffers should be initialized via a call to\r
                 *  \ref RingBuffer_InitBuffer() before use.\r
                 */\r
                typedef struct\r
                {\r
-                       uint8_t* In; /**< Current storage location in the circular buffer */\r
-                       uint8_t* Out; /**< Current retrieval location in the circular buffer */\r
-                       uint8_t* Start; /** Pointer to the start of the buffer's underlying storage array */\r
-                       uint8_t* End; /** Pointer to the end of the buffer's underlying storage array */\r
-                       uint8_t  Size; /** Size of the buffer's underlying storage array */\r
-                       uint16_t Count; /** Number of bytes currently stored in the buffer */\r
-               } RingBuff_t;\r
+                       uint8_t* In; /**< Current storage location in the circular buffer. */\r
+                       uint8_t* Out; /**< Current retrieval location in the circular buffer. */\r
+                       uint8_t* Start; /**< Pointer to the start of the buffer's underlying storage array. */\r
+                       uint8_t* End; /**< Pointer to the end of the buffer's underlying storage array. */\r
+                       uint8_t  Size; /**< Size of the buffer's underlying storage array. */\r
+                       uint16_t Count; /**< Number of bytes currently stored in the buffer. */\r
+               } RingBuffer_t;\r
 \r
        /* Inline Functions: */\r
                /** Initializes a ring buffer ready for use. Buffers must be initialized via this function\r
                 *  before any operations are called upon them. Already initialized buffers may be reset\r
                 *  by re-initializing them using this function.\r
                 *\r
-                *  \param[out] Buffer   Pointer to a ring buffer structure to initialize\r
-                *  \param[out] DataPtr  Pointer to a global array that will hold the data stored into the ring buffer\r
-                *  \param[out] Size     Maximum number of bytes that can be stored in the underlying data array\r
+                *  \param[out] Buffer   Pointer to a ring buffer structure to initialize.\r
+                *  \param[out] DataPtr  Pointer to a global array that will hold the data stored into the ring buffer.\r
+                *  \param[out] Size     Maximum number of bytes that can be stored in the underlying data array.\r
                 */\r
-               static inline void RingBuffer_InitBuffer(RingBuff_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)\r
+               static inline void RingBuffer_InitBuffer(RingBuffer_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)\r
                {\r
-                       ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
-                       {\r
-                               GCC_FORCE_POINTER_ACCESS(Buffer);\r
-                               \r
-                               Buffer->In     = DataPtr;\r
-                               Buffer->Out    = DataPtr;\r
-                               Buffer->Start  = &DataPtr[0];\r
-                               Buffer->End    = &DataPtr[Size];\r
-                               Buffer->Size   = Size;\r
-                               Buffer->Count  = 0;\r
-                       }\r
+                       GCC_FORCE_POINTER_ACCESS(Buffer);\r
+\r
+                       uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+                       GlobalInterruptDisable();\r
+       \r
+                       Buffer->In     = DataPtr;\r
+                       Buffer->Out    = DataPtr;\r
+                       Buffer->Start  = &DataPtr[0];\r
+                       Buffer->End    = &DataPtr[Size];\r
+                       Buffer->Size   = Size;\r
+                       Buffer->Count  = 0;\r
+\r
+                       SetGlobalInterruptMask(CurrentGlobalInt);\r
                }\r
 \r
                /** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed\r
                 *        the returned number should be used only to determine how many successive reads may safely\r
                 *        be performed on the buffer.\r
                 *\r
-                *  \param[in] Buffer  Pointer to a ring buffer structure whose count is to be computed\r
+                *  \param[in] Buffer  Pointer to a ring buffer structure whose count is to be computed.\r
                 */\r
-               static inline uint16_t RingBuffer_GetCount(RingBuff_t* const Buffer)\r
+               static inline uint16_t RingBuffer_GetCount(RingBuffer_t* const Buffer)\r
                {\r
                        uint16_t Count;\r
 \r
-                       ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
-                       {\r
-                               Count = Buffer->Count;\r
-                       }\r
+                       uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+                       GlobalInterruptDisable();\r
+                       \r
+                       Count = Buffer->Count;\r
 \r
+                       SetGlobalInterruptMask(CurrentGlobalInt);\r
                        return Count;\r
                }\r
 \r
                 *  be tested before storing data to the buffer, to ensure that no data is lost due to a\r
                 *  buffer overrun.\r
                 *\r
-                *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into\r
+                *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into.\r
                 *\r
-                *  \return Boolean true if the buffer contains no free space, false otherwise\r
+                *  \return Boolean \c true if the buffer contains no free space, false otherwise.\r
                 */\r
-               static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)\r
+               static inline bool RingBuffer_IsFull(RingBuffer_t* const Buffer)\r
                {\r
                        return (RingBuffer_GetCount(Buffer) == Buffer->Size);\r
                }\r
                 *  buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable\r
                 *  to reduce the time spent in atomicity locks.\r
                 *\r
-                *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into\r
+                *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into.\r
                 *\r
-                *  \return Boolean true if the buffer contains no free space, false otherwise\r
+                *  \return Boolean \c true if the buffer contains no free space, false otherwise.\r
                 */\r
-               static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)\r
+               static inline bool RingBuffer_IsEmpty(RingBuffer_t* const Buffer)\r
                {\r
                        return (RingBuffer_GetCount(Buffer) == 0);\r
                }\r
                 *        otherwise data corruption may occur. Insertion and removal may occur from different execution\r
                 *        threads.\r
                 *\r
-                *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into\r
-                *  \param[in]     Data    Data element to insert into the buffer\r
+                *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into.\r
+                *  \param[in]     Data    Data element to insert into the buffer.\r
                 */\r
-               static inline void RingBuffer_Insert(RingBuff_t* const Buffer,\r
+               static inline void RingBuffer_Insert(RingBuffer_t* Buffer,\r
                                                     const uint8_t Data)\r
                {\r
+                       GCC_FORCE_POINTER_ACCESS(Buffer);\r
+\r
                        *Buffer->In = Data;\r
 \r
                        if (++Buffer->In == Buffer->End)\r
                          Buffer->In = Buffer->Start;\r
 \r
-                       ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
-                       {\r
-                               Buffer->Count++;\r
-                       }\r
+                       uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+                       GlobalInterruptDisable();\r
+                       \r
+                       Buffer->Count++;\r
+\r
+                       SetGlobalInterruptMask(CurrentGlobalInt);\r
                }\r
 \r
                /** Removes an element from the ring buffer.\r
                 *        otherwise data corruption may occur. Insertion and removal may occur from different execution\r
                 *        threads.\r
                 *\r
-                *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from\r
+                *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from.\r
                 *\r
-                *  \return Next data element stored in the buffer\r
+                *  \return Next data element stored in the buffer.\r
                 */\r
-               static inline uint8_t RingBuffer_Remove(RingBuff_t* const Buffer)\r
+               static inline uint8_t RingBuffer_Remove(RingBuffer_t* Buffer)\r
                {\r
+                       GCC_FORCE_POINTER_ACCESS(Buffer);\r
+               \r
                        uint8_t Data = *Buffer->Out;\r
 \r
                        if (++Buffer->Out == Buffer->End)\r
                          Buffer->Out = Buffer->Start;\r
 \r
-                       ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
-                       {\r
-                               Buffer->Count--;\r
-                       }\r
+                       uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+                       GlobalInterruptDisable();\r
+                       \r
+                       Buffer->Count--;\r
+\r
+                       SetGlobalInterruptMask(CurrentGlobalInt);\r
 \r
                        return Data;\r
                }\r
 \r
                /** Returns the next element stored in the ring buffer, without removing it.\r
                 *\r
-                *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from\r
+                *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from.\r
                 *\r
-                *  \return Next data element stored in the buffer\r
+                *  \return Next data element stored in the buffer.\r
                 */\r
-               static inline uint8_t RingBuffer_Peek(RingBuff_t* const Buffer)\r
+               static inline uint8_t RingBuffer_Peek(RingBuffer_t* const Buffer)\r
                {\r
                        return *Buffer->Out;\r
                }\r
 \r
+       /* Disable C linkage for C++ Compilers: */\r
+               #if defined(__cplusplus)\r
+                       }\r
+               #endif\r
+\r
 #endif\r
 \r
 /** @} */\r