Looks like I didn't understood that placing '=0' makes method pure virtual.
Why do we put '=0' (besides compiler distinquishing virtual from pure virtual method), what compiler does when he sees '=0'.
I splitted original interface into two interfaces
#1 Interface
Code:
class Transmitter
{
public:
virtual int write(unsigned char* bytes) = 0;
virtual bool writeByte(unsigned char byte) = 0;
virtual bool write(unsigned char* byte, unsigned char offset, unsigned char length) = 0;
};
Code:
class SerialCommTransmitter : public Transmitter
{
private:
CircularBuffer txQueue;
public:
bool writeByte(unsigned char byte)
{
// wait until queue is empty
while (txQueue.isEmpty());
// check if byte is successfully pushed into queue
if (txQueue.enqueue(byte))
return true;
return false;
}
bool write(unsigned char* bytes, unsigned char offset, unsigned char length)
{
int bytesWrittenCnt = 0;
// wait until all data is send to the buffer
// Problem: što ako je RED popunjen, a svi bytovi nisu writeani
isInterruptEnabled = false;
for (int i = offset; i < length; i++)
{
if (writeByte(bytes[bytesWrittenCnt]))
bytesWrittenCnt++;
}
isInterruptEnabled = true;
return bytesWrittenCnt;
}
int write(unsigned char* bytes)
{
int bytesWrittenCnt = 0;
isInterruptEnabled = false;
// wait untill all data is send to the buffer
// Problem: što ako je RED popunjen, a svi bytovi nisu writeani
while (bytes[bytesWrittenCnt] != '\0')
{
if (writeByte(bytes[bytesWrittenCnt]))
bytesWrittenCnt++;
}
isInterruptEnabled = true;
return bytesWrittenCnt;
}
};
#2 Inteface
Code:
class Receiver
{
public:
virtual bool readByte(unsigned char* byte) = 0;
virtual unsigned char* read() = 0;
};
Code:
class SerialCommReceiver : public Receiver
{
private:
CircularBuffer rxQueue;
public:
bool readByte(unsigned char* byte)
{
if (!rxQueue.isEmpty())
{
rxQueue.dequeue(byte);
return true;
}
return false;
}
unsigned char* read()
{
unsigned char bytesWrittenCnt = 0;
unsigned char* byte = (unsigned char*)malloc(sizeof(unsigned char));
// PROBLEM: ne znamo koliko cemo dugo cekati na read jer se kroz citanje može konstantno dešavati
// receive interrupt, te stoga ne znamo koliko veliki buffer moramo alocirati
unsigned char rxBuffer[BUFFER_SIZE];
while (readByte(byte))
{
rxBuffer[bytesWrittenCnt++] = *byte;
}
return rxBuffer;
}
};
Code:
class SerialPort
{
private:
unsigned int baudRate;
SerialCommReceiver serialReceiver;
SerialCommTransmitter serialTransmitter;
public:
SerialPort(int baudRate)
{
this->baudRate = baudRate;
}
unsigned char* read()
{
return serialReceiver.read();
}
};
If I want to use constant object field in any of classes without passing reference to the constructor do I need to instantiate them like in Java/C# with new operator?
Code:
class SerialPort
{
private:
unsigned int baudRate;
SerialCommReceiver serialReceiver = new SerialCommReceiver();
SerialCommTransmitter serialTransmitter = new SerialCommTransmitter();
public:
SerialPort(int baudRate)
{
this->baudRate = baudRate;
}
unsigned char* read()
{
return serialReceiver.read();
}
};
Also if I want to use my class methods with Interrupts and I am interested if the following approach work:
Since ATMega micrcocontroller header file where all interrupt ISR functions are declared is written in C I use extern "C" keyword
Code:
extern "C" void UART0_UDRE_vect(void) __attribute__ ((signal));
extern "C" void USART0_RX_vect(void) __attribute__ ((signal));
Code:
class SerialPort
{
private:
unsigned int baudRate;
SerialCommReceiver serialReceiver;
SerialCommTransmitter serialTransmitter;
static SerialPort* rxPointer;
static SerialPort* txPointer;
public:
friend void UART0_UDRE_vect(void);
friend void USART0_RX_vect(void);
SerialPort(int baudRate)
{
this->baudRate = baudRate;
rxPointer = this;
txPointer = this;
}
unsigned char* read()
{
return serialReceiver.read();
}
};
And then using SerialPort class methods via SerialPort pointers in ISRs
Code:
void UART0_UDRE_vect(void);
{
unsigned char* byte = (unsigned char*)malloc(sizeof(unsigned char)); // je li ova varijabla treba biti static volatile ?
/* Check if all data is transmitted */
if (txPointer->read(byte)))
{
UDR1 = *byte;
}
}