This repository has been archived on 2025-02-01. You can view files and clone it, but cannot push or open issues or pull requests.
reprapfirmware-dc42/OutputMemory.h
David Crocker f5c4bdc770 Version 1.09r
Added timeout to output buffers destined for USB
Fixed bugs in thermocouple code
Reallocated thermocouple pin numbers
Made Roland mill and inkjet support conditional and normally disabled
Fixed issue with thermocouple code messing up the timekeeping system,
which was suspected of causing the network to be unreliable
Added support for M577 (thanks chrishamm)
2016-01-16 23:10:36 +00:00

151 lines
4.6 KiB
C++

/*
* OutputMemory.h
*
* Created on: 10 Jan 2016
* Authors: David and Christian
*/
#ifndef OUTPUTMEMORY_H_
#define OUTPUTMEMORY_H_
#include "Arduino.h"
#include "Configuration.h"
#include "StringRef.h"
const size_t OUTPUT_STACK_DEPTH = 4; // Number of OutputBuffer chains that can be pushed onto one stack instance
class OutputStack;
// This class is used to hold data for sending (either for Serial or Network destinations)
class OutputBuffer
{
public:
friend class OutputStack;
OutputBuffer(OutputBuffer *n) : next(n) { }
void Append(OutputBuffer *other);
OutputBuffer *Next() const { return next; }
bool IsReferenced() const { return isReferenced; }
void IncreaseReferences(size_t refs);
const char *Data() const { return data; }
size_t DataLength() const { return dataLength; } // How many bytes have been written to this instance?
size_t Length() const; // How many bytes have been written to the whole chain?
char& operator[](size_t index);
char operator[](size_t index) const;
const char *Read(size_t len);
size_t BytesLeft() const { return dataLength - bytesRead; } // How many bytes have not been sent yet?
int printf(const char *fmt, ...);
int vprintf(const char *fmt, va_list vargs);
int catf(const char *fmt, ...);
size_t copy(const char c);
size_t copy(const char *src);
size_t copy(const char *src, size_t len);
size_t cat(const char c);
size_t cat(const char *src);
size_t cat(const char *src, size_t len);
size_t cat(StringRef &str);
size_t EncodeString(const char *src, size_t srcLength, bool allowControlChars, bool encapsulateString = true);
size_t EncodeReply(OutputBuffer *src, bool allowControlChars);
uint32_t GetAge() const;
// Initialise the output buffers manager
static void Init();
// Allocate an unused OutputBuffer instance. Returns true on success or false if no instance could be allocated.
// Setting isAppending to true will guarantee that one OutputBuffer will remain available for single allocation.
static bool Allocate(OutputBuffer *&buf, bool isAppending = false);
// Get the number of bytes left for allocation. If writingBuffer is not NULL, this returns the number of free bytes for
// continuous writes, i.e. for writes that need to allocate an extra OutputBuffer instance to finish the message.
static size_t GetBytesLeft(const OutputBuffer *writingBuffer);
// Truncate an OutputBuffer instance to free up more memory. Returns the number of released bytes.
static size_t Truncate(OutputBuffer *buffer, size_t bytesNeeded);
// Release one OutputBuffer instance. Returns the next item from the chain or nullptr if this was the last instance.
static OutputBuffer *Release(OutputBuffer *buf);
// Release all OutputBuffer objects in a chain
static void ReleaseAll(OutputBuffer *buf);
static void Diagnostics();
private:
OutputBuffer *next;
OutputBuffer *last;
uint32_t whenQueued;
char data[OUTPUT_BUFFER_SIZE];
size_t dataLength, bytesRead;
bool isReferenced;
size_t references;
static OutputBuffer * volatile freeOutputBuffers; // Messages may also be sent by ISRs,
static volatile size_t usedOutputBuffers; // so make these volatile.
static volatile size_t maxUsedOutputBuffers;
};
inline uint32_t OutputBuffer::GetAge() const
{
return millis() - whenQueued;
}
// This class is used to manage references to OutputBuffer chains for all output destinations
class OutputStack
{
public:
OutputStack() : count(0) { }
// Is there anything on this stack?
bool IsEmpty() const { return count == 0; }
// Clear the reference list
void Clear() { count = 0; }
// Push an OutputBuffer chain
void Push(OutputBuffer *buffer);
// Pop an OutputBuffer chain or return NULL if none is available
OutputBuffer *Pop();
// Returns the first item from the stack or NULL if none is available
OutputBuffer *GetFirstItem() const;
// Set the first item of the stack. If it's NULL, then the first item will be removed
void SetFirstItem(OutputBuffer *buffer);
// Returns the last item from the stack or NULL if none is available
OutputBuffer *GetLastItem() const;
// Get the total length of all queued buffers
size_t DataLength() const;
// Append another OutputStack to this instance. If no more space is available,
// all OutputBuffers that can't be added are automatically released
void Append(OutputStack *stack);
// Increase the number of references for each OutputBuffer on the stack
void IncreaseReferences(size_t num);
// Release all buffers and clean up
void ReleaseAll();
private:
volatile size_t count;
OutputBuffer * volatile items[OUTPUT_STACK_DEPTH];
};
#endif /* OUTPUTMEMORY_H_ */
// vim: ts=4:sw=4