Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: azonenberg/stm32-cpp
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 94ac98011405
Choose a base ref
...
head repository: azonenberg/stm32-cpp
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 04ad3a71b64c
Choose a head ref
  • 1 commit
  • 7 files changed
  • 1 contributor

Commits on Jul 6, 2020

  1. Copy the full SHA
    04ad3a7 View commit details
Showing with 387 additions and 218 deletions.
  1. +1 −216 src/peripheral/UART.cpp
  2. +0 −2 src/peripheral/UART.h
  3. +52 −0 src/util/CharacterDevice.cpp
  4. +16 −0 src/util/CharacterDevice.h
  5. +61 −0 src/util/StringBuffer.h
  6. +217 −0 src/util/StringHelpers.cpp
  7. +40 −0 src/util/StringHelpers.h
217 changes: 1 addition & 216 deletions src/peripheral/UART.cpp
Original file line number Diff line number Diff line change
@@ -32,63 +32,10 @@
#include <string.h>
#include <peripheral/UART.h>
#include <peripheral/RCC.h>
#include <util/StringHelpers.h>

extern UART* g_uart;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Helpers for string manipulation

char* reverse(char* s);
char* itoa(int n, char* s);

/**
@brief Reverses a string in-place (K&R implementation)
@param s Input
@return s after reversing
*/
char* reverse(char* s)
{
int i, j;
char c;

for (i = 0, j = strlen(s)-1; i<j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
return s;
}

/**
@brief Converts an int to a string (K&R implementation)
@param n Input
@param s String to store into (must be 12+ bytes long to hold any possible integer)
@return str
*/
char* itoa(int n, char* s)
{
int i, sign;

if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do
{ /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';
s[i] = '\0';

return reverse(s);
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UART driver class

@@ -131,165 +78,3 @@ void UART::PrintBinary(char ch)
while(0 == (m_txlane->ISR & USART_ISR_TXE))
{}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Output formatting

void UART::WritePadded(const char* str, int minlen, char padding, int prepad)
{
int len = strlen(str);
int npads = minlen - len;

if(npads < 0)
npads = 0;

if(prepad)
for(int i=0; i<npads; i++)
PrintBinary(padding);

PrintString(str);

if(!prepad)
for(int i=0; i<npads; i++)
PrintBinary(padding);
}

/**
@brief Stripped-down printf implementation adapted from my old PICNIX project.
Much ligher than a full ANSI compatible version but good enough for typical embedded use.
*/
void UART::Printf(const char* format, ...)
{
__builtin_va_list list;
__builtin_va_start(list, format);

//Parsing helpers
const int buflen = 32; //must be large enough for INT_MAX plus null
char buf[buflen+1];
const char* pch;
int bufpos = 0;
static const char hex[] = "0123456789abcdef";
static const char Hex[] = "0123456789ABCDEF";
unsigned int d;

//Go through the format string and process it
int len = strlen(format);
for(int i=0; i<len; i++)
{
//Format character
if(format[i] == '%')
{
char type; //format code
int length = 0; //min length of field
char padchar = ' '; //padding character
int prepad = 1;

//Flush the buffer
if(bufpos > 0)
{
buf[bufpos] = '\0';
PrintString(buf);
bufpos = 0;
}

//Read specifier
type = format[++i];
if(type == '-')
{
prepad = 0;
type = format[++i];
}
while(isdigit(type))
{
if(type == '0' && length == 0)
padchar = '0';
else
length = (length*10) + (type - '0');
type = format[++i];
}

switch(type)
{
case '%':
PrintBinary('%');
break;

case 'd':
itoa(__builtin_va_arg(list, int), buf);
WritePadded(buf, length, padchar, prepad);
break;

case 'c':
d = __builtin_va_arg(list, int);
PrintBinary(d);
break;

case 's':
pch = __builtin_va_arg(list, const char*);
WritePadded(pch, length, padchar, prepad);
break;

case 'x':
case 'X':
{
d = __builtin_va_arg(list, unsigned int);
int bFirst = 1;
for(int j=0; j<8; j++)
{
//Grab the next 4 bits
unsigned int x = d >> 28;

//Print it
char ch = hex[x];
if(format[i] == 'X') //capitalize
ch = Hex[x];

//Skip leading zeros unless we are padding
//but print a single 0 if it's zero
if( (ch == '0') && bFirst && (j != 7) )
{
if( (8 - j) <= length)
PrintBinary(padchar);
}
else
{
PrintBinary(ch);
bFirst = 0;
}

//Shift off what we just printed
d <<= 4;
}
}
break;

default:
PrintBinary('*');
break;
}
}

//Nope, print it directly, buffering for improved performance
else
{
if(bufpos >= buflen)
{
buf[bufpos] = '\0';
PrintString(buf);
bufpos = 0;
}

buf[bufpos++] = format[i];
}
}

//Flush the buffer
if(bufpos > 0)
{
buf[bufpos] = '\0';
PrintString(buf);
}

__builtin_va_end(list);
}
2 changes: 0 additions & 2 deletions src/peripheral/UART.h
Original file line number Diff line number Diff line change
@@ -53,8 +53,6 @@ class UART : public CharacterDevice

//TX side
virtual void PrintBinary(char ch);
void Printf(const char* format, ...);
void WritePadded(const char* str, int minlen, char padding, int prepad);

protected:
volatile usart_t* m_txlane;
52 changes: 52 additions & 0 deletions src/util/CharacterDevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/***********************************************************************************************************************
* *
* STM32-CPP v0.1 *
* *
* Copyright (c) 2020 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

#include <stm32fxxx.h>
#include <string.h>
#include <stdio.h>
#include "CharacterDevice.h"

void CharacterDevice::WritePadded(const char* str, int minlen, char padding, int prepad)
{
int len = strlen(str);
int npads = minlen - len;

if(npads < 0)
npads = 0;

if(prepad)
for(int i=0; i<npads; i++)
PrintBinary(padding);

PrintString(str);

if(!prepad)
for(int i=0; i<npads; i++)
PrintBinary(padding);
}
16 changes: 16 additions & 0 deletions src/util/CharacterDevice.h
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@
#define characterdevice_h

#include <util/FIFO.h>
#include <util/StringHelpers.h>

/**
@file
@@ -46,6 +47,21 @@ class CharacterDevice
//Overrides
virtual void PrintBinary(char ch) =0;

//Pretty printing
public:
void WritePadded(const char* str, int minlen, char padding, int prepad);

void Printf(const char* format, ...)
{
__builtin_va_list list;
__builtin_va_start(list, format);
DoPrintf(this, format, list);
__builtin_va_end(list);
}

void Printf(const char* format, __builtin_va_list list)
{ DoPrintf(this, format, list); }

//Convenience wrappers
public:
void PrintText(char ch)
61 changes: 61 additions & 0 deletions src/util/StringBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/***********************************************************************************************************************
* *
* STM32-CPP v0.1 *
* *
* Copyright (c) 2020 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

#ifndef StringBuffer_h
#define StringBuffer_h

#include <stdio.h>
#include <stdint.h>

/**
@brief Helper for formatting strings
*/
class StringBuffer : public CharacterDevice
{
public:
StringBuffer(char* buf, size_t size)
: m_buf(buf)
, m_size(size)
, m_wptr(0)
{
}

virtual void PrintBinary(char ch)
{
if(m_wptr <= m_size)
m_buf[m_wptr ++] = ch;
}

protected:
char* m_buf;
size_t m_size;
size_t m_wptr;
};

#endif
217 changes: 217 additions & 0 deletions src/util/StringHelpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/***********************************************************************************************************************
* *
* STM32-CPP v0.1 *
* *
* Copyright (c) 2020 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

#include <stm32fxxx.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include "StringHelpers.h"
#include "CharacterDevice.h"

/**
@brief Reverses a string in-place (K&R implementation)
@param s Input
@return s after reversing
*/
char* reverse(char* s)
{
int i, j;
char c;

for (i = 0, j = strlen(s)-1; i<j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
return s;
}

/**
@brief Converts an int to a string (K&R implementation)
@param n Input
@param s String to store into (must be 12+ bytes long to hold any possible integer)
@return str
*/
char* itoa(int n, char* s)
{
int i, sign;

if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do
{ /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */

if (sign < 0)
s[i++] = '-';
s[i] = '\0';

return reverse(s);
}

/**
@brief Stripped-down printf implementation adapted from my old PICNIX project.
Much ligher than a full ANSI compatible version but good enough for typical embedded use.
*/
void DoPrintf(CharacterDevice* target, const char* format, __builtin_va_list args)
{
//Parsing helpers
const int buflen = 32; //must be large enough for INT_MAX plus null
char buf[buflen+1];
const char* pch;
int bufpos = 0;
static const char hex[] = "0123456789abcdef";
static const char Hex[] = "0123456789ABCDEF";
unsigned int d;

//Go through the format string and process it
int len = strlen(format);
for(int i=0; i<len; i++)
{
//Format character
if(format[i] == '%')
{
char type; //format code
int length = 0; //min length of field
char padchar = ' '; //padding character
int prepad = 1;

//Flush the buffer
if(bufpos > 0)
{
buf[bufpos] = '\0';
target->PrintString(buf);
bufpos = 0;
}

//Read specifier
type = format[++i];
if(type == '-')
{
prepad = 0;
type = format[++i];
}
while(isdigit(type))
{
if(type == '0' && length == 0)
padchar = '0';
else
length = (length*10) + (type - '0');
type = format[++i];
}

switch(type)
{
case '%':
target->PrintBinary('%');
break;

case 'd':
itoa(__builtin_va_arg(args, int), buf);
target->WritePadded(buf, length, padchar, prepad);
break;

case 'c':
d = __builtin_va_arg(args, int);
target->PrintBinary(d);
break;

case 's':
pch = __builtin_va_arg(args, const char*);
target->WritePadded(pch, length, padchar, prepad);
break;

case 'x':
case 'X':
{
d = __builtin_va_arg(args, unsigned int);
int bFirst = 1;
for(int j=0; j<8; j++)
{
//Grab the next 4 bits
unsigned int x = d >> 28;

//Print it
char ch = hex[x];
if(format[i] == 'X') //capitalize
ch = Hex[x];

//Skip leading zeros unless we are padding
//but print a single 0 if it's zero
if( (ch == '0') && bFirst && (j != 7) )
{
if( (8 - j) <= length)
target->PrintBinary(padchar);
}
else
{
target->PrintBinary(ch);
bFirst = 0;
}

//Shift off what we just printed
d <<= 4;
}
}
break;

default:
target->PrintBinary('*');
break;
}
}

//Nope, print it directly, buffering for improved performance
else
{
if(bufpos >= buflen)
{
buf[bufpos] = '\0';
target->PrintString(buf);
bufpos = 0;
}

buf[bufpos++] = format[i];
}
}

//Flush the buffer
if(bufpos > 0)
{
buf[bufpos] = '\0';
target->PrintString(buf);
}
}
40 changes: 40 additions & 0 deletions src/util/StringHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/***********************************************************************************************************************
* *
* STM32-CPP v0.1 *
* *
* Copyright (c) 2020 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

#ifndef StringHelpers_h
#define StringHelpers_h

class CharacterDevice;

char* reverse(char* s);
char* itoa(int n, char* s);

void DoPrintf(CharacterDevice* target, const char* format, __builtin_va_list args);

#endif