-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bdad3e4
commit cd4f701
Showing
8 changed files
with
1,259 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#pragma once | ||
/// <summary> | ||
/// Fixed size queue (does not call new/delete, so will not lead to memory fragmentation (important on embeded systems)). | ||
/// Items must be POD suitable for memcpy. | ||
/// </summary> | ||
template<typename T, int QCNT> | ||
class FixedSizeQueue { | ||
struct Node | ||
{ | ||
T item; | ||
bool used; | ||
}; | ||
|
||
Node m_queue[QCNT]; | ||
|
||
public: | ||
FixedSizeQueue (){ clear(); } | ||
|
||
void clear() | ||
{ | ||
memset(&m_queue, 0, sizeof(m_queue)); | ||
} | ||
|
||
bool push (const T& i) | ||
{ | ||
int pos = findEmpty(); | ||
if(pos == -1) | ||
{ | ||
return false; | ||
} | ||
|
||
memcpy(&m_queue[pos].item, &i, sizeof(T)); | ||
m_queue[pos].used = true; | ||
return true; | ||
} | ||
|
||
// pop an item from the queue. | ||
T pop () | ||
{ | ||
T res = m_queue[0].item; | ||
|
||
//shift all down: | ||
for(int ix=1; ix<QCNT; ix++) | ||
{ | ||
memcpy(&m_queue[ix-1], &m_queue[ix], sizeof(Node)); | ||
memset(&m_queue[ix], 0, sizeof(Node)); | ||
} | ||
|
||
return res; | ||
} | ||
|
||
const T& peek () const { return m_queue[0].item; } | ||
bool isEmpty () const { return m_queue[0].used == false; } | ||
bool isFull () const { return m_queue[QCNT-1].used; } | ||
|
||
// get the number of items in the queue. | ||
int count () const | ||
{ | ||
for(int ix=0; ix<QCNT; ix++) | ||
{ | ||
if(m_queue[ix].used == false) | ||
{ | ||
return ix; | ||
} | ||
} | ||
|
||
return QCNT; | ||
} | ||
|
||
private: | ||
int findEmpty() const | ||
{ | ||
for(int ix=0; ix<QCNT; ix++) | ||
{ | ||
if(m_queue[ix].used == false) | ||
{ | ||
return ix; | ||
} | ||
} | ||
|
||
return -1; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#pragma once | ||
#include <string.h> | ||
//content is populated only once, on download, so it's OK to use dynamic memory allocation even on embeded devices | ||
#define MAX_PAGES_CNT 15 | ||
#define MAX_PAGE_SIZE 0x100 | ||
class MemoryMap | ||
{ | ||
unsigned char* m_tblPages[MAX_PAGES_CNT]; | ||
|
||
//prevent copy operations: | ||
MemoryMap(const MemoryMap& rhs); | ||
MemoryMap& operator=(const MemoryMap& rhs); | ||
|
||
int Access(bool read, int iPage, int iIndex, int iToAccessBytes, unsigned char* buffer) | ||
{ | ||
if(read && Exist(iPage) == false) | ||
{ | ||
return 0; | ||
} | ||
|
||
int totalAccessed = 0; | ||
while(iToAccessBytes > 0) | ||
{ | ||
unsigned char* pPage = GetPage(iPage); | ||
if(pPage == NULL) | ||
{ | ||
//DEBUG(LOG_ERR, "Requested too large page: %d", iPage); | ||
break; | ||
} | ||
|
||
if(iIndex + iToAccessBytes <= MAX_PAGE_SIZE) | ||
{ | ||
//read/write fits the page | ||
if(read) | ||
{ | ||
memcpy(buffer, pPage+iIndex, iToAccessBytes); | ||
} | ||
else | ||
{ | ||
memcpy(pPage+iIndex, buffer, iToAccessBytes); | ||
} | ||
|
||
totalAccessed += iToAccessBytes; | ||
buffer += iToAccessBytes; | ||
iToAccessBytes = 0; | ||
} | ||
else | ||
{ | ||
//read/write spans more than one page, let's remaining ammount from current one | ||
int iFree = MAX_PAGE_SIZE - iIndex; | ||
if(read) | ||
{ | ||
memcpy(buffer, pPage+iIndex, iFree); | ||
} | ||
else | ||
{ | ||
memcpy(pPage+iIndex, buffer, iFree); | ||
} | ||
|
||
totalAccessed += iFree; | ||
buffer += iFree; | ||
iToAccessBytes -= iFree; | ||
|
||
//Set it to the next page and index to 0 | ||
iPage += 1; | ||
iIndex = 0; | ||
} | ||
} | ||
|
||
return totalAccessed; | ||
} | ||
|
||
public: | ||
MemoryMap() | ||
{ | ||
memset(m_tblPages, 0, sizeof(m_tblPages)); | ||
} | ||
|
||
~MemoryMap() | ||
{ | ||
Clear(); | ||
} | ||
|
||
void Clear() | ||
{ | ||
for(int ix=0; ix<MAX_PAGES_CNT; ix++) | ||
{ | ||
delete [] m_tblPages[ix]; | ||
m_tblPages[ix] = NULL; | ||
} | ||
} | ||
|
||
bool Exist(int iPage) const | ||
{ | ||
if(iPage<0 || iPage>=MAX_PAGES_CNT) | ||
{ | ||
return false; | ||
} | ||
|
||
return m_tblPages[iPage] != NULL; | ||
} | ||
|
||
unsigned char* GetPage(int iPage) | ||
{ | ||
if(iPage<0 || iPage>=MAX_PAGES_CNT) | ||
{ | ||
return NULL; | ||
} | ||
|
||
if(m_tblPages[iPage] != NULL) | ||
{ | ||
return m_tblPages[iPage]; | ||
} | ||
|
||
m_tblPages[iPage] = new unsigned char[MAX_PAGE_SIZE]; | ||
memset(m_tblPages[iPage], 0xFF, MAX_PAGE_SIZE); | ||
return m_tblPages[iPage]; | ||
} | ||
|
||
int Read(int iPage, int iIndex, int iToReadBytes, void* bufferOut) | ||
{ | ||
return Access(true, iPage, iIndex, iToReadBytes, (unsigned char*)bufferOut); | ||
} | ||
|
||
int Write(int iPage, int iIndex, int iToWriteBytes, const void* bufferIn) | ||
{ | ||
return Access(false, iPage, iIndex, iToWriteBytes, (unsigned char*)bufferIn); | ||
} | ||
}; |
Oops, something went wrong.