keyboard input buffering

main
Clyne 3 weeks ago
parent fffe935266
commit b480537a27
Signed by: clyne
GPG Key ID: 1B74EE6C49C96795

@ -1,5 +1,5 @@
CXXFLAGS := -m32 -ggdb -g3 -O0 -fno-pic -ffreestanding -fno-rtti -fno-exceptions -std=c++23
LDFLAGS := -m32 -static -T link.ld -ffreestanding -nostdlib
CXXFLAGS := -m32 -ggdb -g3 -O0 -fno-pic -fno-rtti -fno-exceptions -std=c++23
LDFLAGS := $(CXXFLAGS) -T link.ld -static -nostdlib -fno-use-cxa-atexit
CXXFILES := acpi.cpp \
boot.cpp \

@ -0,0 +1,573 @@
/*
MIT License
Copyright (c) 2020 Vinit James
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#include <algorithm>
#include <iterator>
#include <mutex>
#include <memory>
#include <stdexcept>
#include <utility>
template<typename T>
class CircularBuffer {
private:
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template <bool isConst> struct BufferIterator;
public:
typedef T value_type;
// clyne
constexpr CircularBuffer()
:_buff{}, _max_size{0} {}
explicit CircularBuffer(size_t size)
:_buff{std::unique_ptr<T[]>(new value_type[size])}, _max_size{size}{}
CircularBuffer(const CircularBuffer& other)
:_buff{std::unique_ptr<T[]>(new value_type[other._max_size])},
_max_size{other._max_size},
_size{other._size},
_head{other._head},
_tail{other._tail}{
std::copy(other.data(), other.data() + _max_size, _buff.get());
}
CircularBuffer& operator=(const CircularBuffer& other){
if ( this != &other){
_buff.reset(new value_type[other._max_size]);
_max_size = other._max_size;
_size = other._size;
_head = other._head;
_tail = other._tail;
std::copy(other.data(), other.data() + _max_size, _buff.get());
}
return *this;
}
CircularBuffer(CircularBuffer&& other) noexcept
:_buff{std::move(other._buff)},
_max_size{other._max_size},
_size{other._size},
_head{other._head},
_tail{other._tail}{
other._buff = nullptr;
other._max_size = 0;
other._size = 0;
other._head = 0;
other._tail = 0;
}
CircularBuffer& operator=(CircularBuffer&& other) noexcept{
if ( this != &other){
_buff = std::move(other._buff);
_max_size = other._max_size;
_size = other._size;
_head = other._head;
_tail = other._tail;
other._buff = nullptr;
other._max_size = 0;
other._size = 0;
other._head = 0;
other._tail = 0;
}
return *this;
}
void push_back(const value_type& data);
void push_back(value_type&& data) noexcept;
void pop_front();
reference front();
reference back();
const_reference front() const;
const_reference back() const;
void clear();
bool empty() const ;
bool full() const ;
size_type capacity() const ;
size_type size() const;
size_type buffer_size() const {return sizeof(value_type)*_max_size;};
const_pointer data() const { return _buff.get(); }
const_reference operator[](size_type index) const;
reference operator[](size_type index);
const_reference at(size_type index) const;
reference at(size_type index);
typedef BufferIterator<false> iterator;
typedef BufferIterator<true> const_iterator;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
iterator rbegin() noexcept;
const_iterator rbegin() const noexcept;
iterator rend() noexcept;
const_iterator rend() const noexcept;
private:
void _increment_bufferstate();
void _decrement_bufferstate();
// clyne
//mutable std::mutex _mtx;
std::unique_ptr<value_type[]> _buff;
size_type _head = 0;
size_type _tail = 0;
size_type _size = 0;
size_type _max_size = 0;
template<bool isConst = false>
struct BufferIterator{
public:
friend class CircularBuffer<T>;
typedef std::random_access_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef typename std::conditional<isConst, const value_type&, value_type&>::type reference;
typedef typename std::conditional<isConst, const value_type*, value_type*>::type pointer;
typedef typename std::conditional<isConst, const CircularBuffer<value_type>*,
CircularBuffer<value_type>*>::type cbuf_pointer;
private:
cbuf_pointer _ptrToBuffer;
size_type _offset;
size_type _index;
bool _reverse;
bool _comparable(const BufferIterator<isConst>& other) const{
return (_ptrToBuffer == other._ptrToBuffer)&&(_reverse == other._reverse);
}
public:
BufferIterator()
:_ptrToBuffer{nullptr}, _offset{0}, _index{0}, _reverse{false}{}
BufferIterator(const BufferIterator<false>& it)
:_ptrToBuffer{it._ptrToBuffer},
_offset{it._offset},
_index{it._index},
_reverse{it._reverse}{}
reference operator*(){
if(_reverse)
return (*_ptrToBuffer)[(_ptrToBuffer->size() - _index - 1)];
return (*_ptrToBuffer)[_index];
}
pointer operator->() { return &(operator*()); }
reference operator[](size_type index){
BufferIterator iter = *this;
iter._index += index;
return *iter;
}
BufferIterator& operator++(){
++_index;
return *this;
}
BufferIterator operator++(int){
BufferIterator iter = *this;
++_index;
return iter;
}
BufferIterator& operator--(){
--_index;
return *this;
}
BufferIterator operator--(int){
BufferIterator iter = *this;
--_index;
return iter;
}
friend BufferIterator operator+(BufferIterator lhsiter, difference_type n){
lhsiter._index += n;
return lhsiter;
}
friend BufferIterator operator+(difference_type n, BufferIterator rhsiter){
rhsiter._index += n;
return rhsiter;
}
BufferIterator& operator+=(difference_type n){
_index += n;
return *this;
}
friend BufferIterator operator-(BufferIterator lhsiter, difference_type n){
lhsiter._index -= n;
return lhsiter;
}
friend difference_type operator-(const BufferIterator& lhsiter, const BufferIterator& rhsiter){
return lhsiter._index - rhsiter._index;
}
BufferIterator& operator-=(difference_type n){
_index -= n;
return *this;
}
bool operator==(const BufferIterator& other) const{
if (!_comparable(other))
return false;
return ((_index == other._index)&&(_offset == other._offset));
}
bool operator!=(const BufferIterator& other) const{
if (!_comparable(other))
return true;
return ((_index != other._index)||(_offset != other._offset));
}
bool operator<(const BufferIterator& other) const {
if (!_comparable(other))
return false;
return ((_index + _offset)<(other._index+other._offset));
}
bool operator>(const BufferIterator& other) const{
if (!_comparable(other))
return false;
return ((_index + _offset)>(other._index+other._offset));
}
bool operator<=(const BufferIterator& other) const {
if (!_comparable(other))
return false;
return ((_index + _offset)<=(other._index+other._offset));
}
bool operator>=(const BufferIterator& other) const {
if (!_comparable(other))
return false;
return ((_index + _offset)>=(other._index+other._offset));
}
};
};
template<typename T>
inline
bool CircularBuffer<T>::full() const{
return _size == _max_size;
}
template<typename T>
inline
bool CircularBuffer<T>::empty() const{
return _size == 0;
}
template<typename T>
inline
typename CircularBuffer<T>::size_type CircularBuffer<T>::capacity() const{
return _max_size;
}
template<typename T>
inline
void CircularBuffer<T>::clear(){
//std::lock_guard<std::mutex> _lck(_mtx);
_head = _tail = _size = 0;
}
template<typename T>
inline
typename CircularBuffer<T>::size_type CircularBuffer<T>::size() const{
//std::lock_guard<std::mutex> _lck(_mtx);
return _size;
}
template<typename T>
inline
typename CircularBuffer<T>::reference CircularBuffer<T>::front() {
//std::lock_guard<std::mutex> _lck(_mtx);
// clyne
if(empty())
abort(); //throw std::length_error("front function called on empty buffer");
return _buff[_tail];
}
template<typename T>
inline
typename CircularBuffer<T>::reference CircularBuffer<T>::back() {
//std::lock_guard<std::mutex> _lck(_mtx);
if(empty())
abort(); //throw std::length_error("back function called on empty buffer");
return _head == 0 ? _buff[_max_size - 1] : _buff[_head - 1];
}
template<typename T>
inline
typename CircularBuffer<T>::const_reference CircularBuffer<T>::front() const{
//std::lock_guard<std::mutex> _lck(_mtx);
if(empty())
abort(); //throw std::length_error("front function called on empty buffer");
return _buff[_tail];
}
template<typename T>
inline
typename CircularBuffer<T>::const_reference CircularBuffer<T>::back() const{
//std::lock_guard<std::mutex> _lck(_mtx);
if(empty())
abort(); //throw std::length_error("back function called on empty buffer");
return _head == 0 ? _buff[_max_size - 1] : _buff[_head - 1];
}
template<typename T>
inline
void CircularBuffer<T>::push_back(const T& data){
//std::lock_guard<std::mutex> _lck(_mtx);
//if(full())
// _buff[_tail].~T();
_buff[_head] = data;
_increment_bufferstate();
}
template<typename T>
inline
void CircularBuffer<T>::push_back(T&& data) noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
_buff[_head] = std::move(data);
_increment_bufferstate();
}
template<typename T>
inline
void CircularBuffer<T>::_increment_bufferstate(){
if(full())
_tail = (_tail + 1)%_max_size;
else
++_size;
_head = (_head + 1)%_max_size;
}
template<typename T>
inline
void CircularBuffer<T>::pop_front(){
//std::lock_guard<std::mutex> _lck(_mtx);
if(empty())
abort(); //throw std::length_error("pop_front called on empty buffer");
_decrement_bufferstate();
}
template<typename T>
inline
void CircularBuffer<T>::_decrement_bufferstate(){
--_size;
_tail = (_tail + 1)%_max_size;
}
template<typename T>
inline
typename CircularBuffer<T>::reference CircularBuffer<T>::operator[](size_t index) {
//std::lock_guard<std::mutex> _lck(_mtx);
if((index<0)||(index>=_size))
abort(); //throw std::out_of_range("Index is out of Range of buffer size");
index += _tail;
index %= _max_size;
return _buff[index];
}
template<typename T>
inline
typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator[](size_t index) const {
//std::lock_guard<std::mutex> _lck(_mtx);
if((index<0)||(index>=_size))
abort(); //throw std::out_of_range("Index is out of Range of buffer size");
index += _tail;
index %= _max_size;
return _buff[index];
}
template<typename T>
inline
typename CircularBuffer<T>::reference CircularBuffer<T>::at(size_t index) {
//std::lock_guard<std::mutex> _lck(_mtx);
if((index<0)||(index>=_size))
abort(); //throw std::out_of_range("Index is out of Range of buffer size");
index += _tail;
index %= _max_size;
return _buff[index];
}
template<typename T>
inline
typename CircularBuffer<T>::const_reference CircularBuffer<T>::at(size_t index) const {
//std::lock_guard<std::mutex> _lck(_mtx);
if((index<0)||(index>=_size))
abort(); //throw std::out_of_range("Index is out of Range of buffer size");
index += _tail;
index %= _max_size;
return _buff[index];
}
template<typename T>
inline
typename CircularBuffer<T>::iterator CircularBuffer<T>::begin() {
//std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = false;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::begin() const{
//std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = false;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::iterator CircularBuffer<T>::end() {
//std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = false;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::end() const{
//std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = false;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cbegin() const noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = false;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cend() const noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = false;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::iterator CircularBuffer<T>::rbegin() noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = true;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rbegin() const noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = true;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::iterator CircularBuffer<T>::rend() noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = true;
return iter;
}
template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rend() const noexcept{
//std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = true;
return iter;
}
#endif /* CIRCULAR_BUFFER_H */

@ -40,35 +40,28 @@ void kernel_main(void)
tasking_initialize();
term.write("Tasking enabled.\n");
//tasking_spawn([] {
// for (;;) {
// do pit_delay_ms(1);
// while (termBusy);
// termBusy = true;
// term.write('B');
// termBusy = false;
// }
//}, 256);
//tasking_spawn([] {
// for (;;) {
// do pit_delay_ms(1);
// while (termBusy);
// termBusy = true;
// term.write('C');
// termBusy = false;
// }
//}, 256);
for (;;) {
pit_delay_ms(100);
//while (termBusy);
const auto ch = keyboard_read();
if (ch)
term.write(*ch);
pit_delay_ms(10);
}
}
//termBusy = true;
//term.write('A');
//termBusy = false;
extern "C"
void abort()
{
term.write("!!! abort() called !!!");
asm volatile("cli");
for (;;);
}
extern "C"
int __cxa_atexit(void (*func)(void *), void *arg, void *dso_handle)
{
return 0;
}
int __dso_handle = 0;

@ -1,33 +1,16 @@
#include "circularbuffer.hpp"
#include "idt.hpp"
#include "keyboard.hpp"
#include "portio.hpp"
#include "vgaterminal.hpp"
#include <array>
#include <cstdint>
#define K_CONTROL_L -1
#define K_SHIFT_L -2
#define K_ALT_L -3
#define K_CAPS -4
#define K_NUM -5
#define K_SCROLL -6
#define K_SHIFT_R -7
#define K_ESCAPE -8
#define K_F1 -10
#define K_F2 -11
#define K_F3 -12
#define K_F4 -13
#define K_F5 -14
#define K_F6 -15
#define K_F7 -16
#define K_F8 -17
#define K_F9 -18
#define K_F10 -19
#define K_F11 -20
#define K_F12 -21
extern TextOutput& term;
static CircularBuffer<char> keyboardBuffer;
static const std::array<char, 0x59> ScanCodeSet1 {{
0, K_ESCAPE,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
@ -52,14 +35,29 @@ static constexpr auto keycode(auto ch) {
void keyboard_initialize()
{
keyboardBuffer = CircularBuffer<char>(128);
idt_register_callback(33, [](auto& regs) {
const auto kc = inb(0x60);
if (!isReleased(kc)) {
const auto ch = ScanCodeSet1[keycode(kc)];
if (ch > 0)
term.write(ch);
//if (ch > 0)
// term.write(ch);
keyboardBuffer.push_back(ch);
}
});
}
std::optional<char> keyboard_read()
{
if (keyboardBuffer.empty()) {
return {};
} else {
const auto ch = keyboardBuffer.front();
keyboardBuffer.pop_front();
return ch;
}
}

@ -1,7 +1,32 @@
#ifndef KEYBOARD_HPP
#define KEYBOARD_HPP
#include <optional>
#define K_CONTROL_L -1
#define K_SHIFT_L -2
#define K_ALT_L -3
#define K_CAPS -4
#define K_NUM -5
#define K_SCROLL -6
#define K_SHIFT_R -7
#define K_ESCAPE -8
#define K_F1 -10
#define K_F2 -11
#define K_F3 -12
#define K_F4 -13
#define K_F5 -14
#define K_F6 -15
#define K_F7 -16
#define K_F8 -17
#define K_F9 -18
#define K_F10 -19
#define K_F11 -20
#define K_F12 -21
void keyboard_initialize();
std::optional<char> keyboard_read();
#endif // KEYBOARD_HPP

@ -85,3 +85,12 @@ void *operator new[](std::size_t size)
return memory_alloc(size);
}
void operator delete(void *ptr)
{
}
void operator delete[](void *ptr)
{
}

@ -1,6 +1,37 @@
#ifndef MEMORY_HPP
#define MEMORY_HPP
#include <cstddef>
#include <type_traits>
template<typename T>
struct kallocator
{
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using propagate_on_container_move_assignment = std::true_type;
using is_always_equal = std::true_type;
template<class U>
struct rebind {
typedef kallocator<U> other;
};
kallocator() = default;
template<typename U>
kallocator(const kallocator<U>&) noexcept {}
T* allocate(std::size_t n) {
return new T[n];
}
void deallocate([[maybe_unused]] T* p, [[maybe_unused]] std::size_t n) {
}
};
void memory_initialize();
#endif // MEMORY_HPP

Loading…
Cancel
Save