Ps2KeyboardHost  1.0.1
Allows you to read from one or more PS2-style keyboards on an Arduino.
ps2_KeyboardOutputBuffer.h
Go to the documentation of this file.
1 /*
2 Copyright (C) 2017 Steve Benz <s8878992@hotmail.com>
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8 
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13 
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 USA
18 */
19 #pragma once
20 
21 #include "ps2_KeyboardOutput.h"
22 #include "ps2_NullDiagnostics.h"
23 #include <util/atomic.h>
24 
25 namespace ps2 {
29  template <uint8_t Size, typename TDiagnostics = NullDiagnostics>
30  class KeyboardOutputBuffer {
31  // These do not need to be marked volatile because of the use of ATOMIC_BLOCK and the requirement
32  // that push be called from within an interrupt.
33  uint8_t head;
34  uint8_t tail;
35  KeyboardOutput buffer[Size];
36  TDiagnostics *diagnostics;
37 
38  const uint8_t EmptyMarker = 0xff;
39 
40  public:
41  KeyboardOutputBuffer(TDiagnostics &diagnostics) {
42  this->head = EmptyMarker;
43  this->tail = 0;
44  this->diagnostics = &diagnostics;
45  };
46 
50  void push(KeyboardOutput valueAtTop) {
51  uint8_t nextTail = (this->tail + 1) % Size;
52  if (this->head == EmptyMarker) {
53  this->head = this->tail;
54  }
55  else if (this->head == this->tail) {
56  this->diagnostics->bufferOverflow();
57  ++this->head;
58  }
59  buffer[this->tail] = valueAtTop;
60  this->tail = nextTail;
61  }
62 
66  KeyboardOutput pop() {
67  KeyboardOutput valueAtTop;
68  ATOMIC_BLOCK(ATOMIC_FORCEON)
69  {
70  if (this->head == EmptyMarker) {
71  valueAtTop = KeyboardOutput::none;
72  }
73  else {
74  valueAtTop = buffer[this->head];
75  int h = (this->head + 1) % Size;
76  this->head = (h == this->tail) ? EmptyMarker : h;
77  }
78  }
79  return valueAtTop;
80  }
81 
82  KeyboardOutput peek() {
83  KeyboardOutput valueAtTop;
84  ATOMIC_BLOCK(ATOMIC_FORCEON)
85  {
86  uint8_t h = this->head;
87  valueAtTop = (h == EmptyMarker) ? KeyboardOutput::none : this->buffer[h];
88  }
89  return valueAtTop;
90  }
91 
92  void clear() {
93  ATOMIC_BLOCK(ATOMIC_FORCEON) {
94  this->head = EmptyMarker;
95  }
96  }
97  };
98 
99 
100  // If the only thing you're driving is the keyboard, then you really don't need a multi-byte buffer.
101 
105  template <typename TDiagnostics>
106  class KeyboardOutputBuffer<1, TDiagnostics> {
107  volatile KeyboardOutput buffer;
108  TDiagnostics *diagnostics;
109 
110  public:
111  KeyboardOutputBuffer(TDiagnostics &diagnostics) {
112  this->diagnostics = &diagnostics;
113  this->buffer = KeyboardOutput::none;
114  };
115 
119  void push(KeyboardOutput valueAtTop) {
120  if (buffer != KeyboardOutput::none) {
121  this->diagnostics->bufferOverflow();
122  }
123  this->buffer = valueAtTop;
124  }
125 
129  KeyboardOutput pop() {
130  KeyboardOutput valueAtTop;
131  ATOMIC_BLOCK(ATOMIC_FORCEON)
132  {
133  valueAtTop = this->buffer;
134  this->buffer = KeyboardOutput::none;
135  }
136  return valueAtTop;
137  }
138 
139  KeyboardOutput peek() {
140  return this->buffer;
141  }
142 
143 
144  void clear() {
145  this->buffer = KeyboardOutput::none;
146  }
147  };
148 }
Definition: ps2_AnsiTranslator.h:24
KeyboardOutput
Byte-codes sent back from the Ps2 keyboard to the host.
Definition: ps2_KeyboardOutput.h:31