added C++ embedded part

This commit is contained in:
Oliver Mueller 2015-06-22 19:14:46 +02:00
parent 3c1c1546b5
commit cd06cf2474
32 changed files with 11854 additions and 0 deletions

1
2015/ppc/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
gps/UnitTest

1
2015/ppc/.ruby-gemset Normal file
View File

@ -0,0 +1 @@
inga

1
2015/ppc/.ruby-version Normal file
View File

@ -0,0 +1 @@
2.1

79
2015/ppc/README.mkd Normal file
View File

@ -0,0 +1,79 @@
# GPS on CAN
In this task you will need to receive Can-frames on the can-bus that contain the GPS location of the
vehicle. The raw data has to be converted to arc-milliseconds
1°2'5" == (1*3600+ 2*60 + 5)*1000
Beware that the system you are running your code on will not support floating point operations.
Use only unsigned and signed integers!
Still the precision of your calculations has to be +-100 milli-arc-seconds
## Conversion to Arc-Degree
inDegree hex = 180/(2^31-1) * (hex) [°]
## GPS Datalayout in CAN Message
Byte7 ST_LAT_NAVI
Byte6 ST_LAT_NAVI
Byte5 ST_LAT_NAVI
Byte4 ST_LAT_NAVI
Byte3 ST_LONG_NAVI
Byte2 ST_LONG_NAVI
Byte1 ST_LONG_NAVI
Byte0 ST_LONG_NAVI
## Byteorder
Little Endian (Least Significant Byte is at lowest address)
## Status Longitude Navigation
ST_LONG_NAVI
### Possible Values
-180° ... +180°
### signal type
32 Bit Signed Integer (Byte 0 ... Byte 3)
### Invalid Data
Invalid-Value: 80 00 00 00h
Signal not available value: 7F FF FF FF
## Status Latitude Navigation
ST_LAT_NAVI
### Possible Values
-180° ... +180°
### signal type
32 Bit Signed Integer (Byte 4 ... Byte 7)
### Invalid Data
Invalid-Value: 80 00 00 00h
Signal not available value: 7F FF FF FF
## Running the tests
you will need a working ruby installation to execute the tests
### Install the bake tool
see https://esrlabs.com/gems/doc/bake-toolkit/
### run the tests
execute `rake run` from this directory

View File

@ -0,0 +1,32 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef COMMON_TYPES_H
#define COMMON_TYPES_H
/* standard types file to be used for
* all C++ basic software components */
#ifdef UNIT_TEST
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long int uint64;
typedef signed char sint8;
typedef signed short sint16;
typedef signed int sint32;
typedef signed long long int sint64;
#else
#include "Std_Types.h"
typedef volatile uint32 vuint32;
typedef volatile uint32 vuint32_t;
#endif
#endif /* COMMON_TYPES_H */

View File

@ -0,0 +1,92 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef COMPILETIMECONSTRAINTS_H_
#define COMPILETIMECONSTRAINTS_H_
#include "commonTypes.h"
#define ZGW_JOIN( X, Y ) ZGW_DO_JOIN( X, Y )
#define ZGW_DO_JOIN( X, Y ) ZGW_DO_JOIN2(X,Y)
#define ZGW_DO_JOIN2( X, Y ) X##Y
namespace common
{
template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
# define ECU_STATIC_ASSERT( B ) \
typedef char ZGW_JOIN(zgw_static_assert_typedef_, __LINE__) \
[ ::common::STATIC_ASSERTION_FAILURE< (bool)( B ) >::value ]
template<bool Condition>
struct CompileTimeError;
template<>
struct CompileTimeError<false> {};
/**
* STATIC_CHECK will fail when expr evaluates to true
*/
#define STATIC_CHECK(msg, expr) \
{ common::CompileTimeError<(expr)> ERROR_##msg; (void)ERROR_##msg; }
/**
* STATIC_ASSERT will fail when expr evaluates to false
* simple usage: STATIC_ASSERT(too_bad_static_assert_failed, 2 > 3)
*/
#define STATIC_ASSERT(msg, expr) \
{ common::CompileTimeError<!(expr)> ERROR_##msg; (void)ERROR_##msg; }
/**
* another example-setup for compile-time-check: a class only has to inherit from this constraint,
* so the constructor of this Constraint has to be compiled and the static check is executed
* by the compiler.
* will only compile if ACTUAL_SIZE <= ALLOWED_SIZE
*
* the argument passed to the STATIC_CHECK-macro can be any allowed C++-identifier,
*/
template<uint32 ACTUAL_SIZE, uint32 ALLOWED_SIZE>
struct ValidSizeConstraint
{
static void constraint()
{
STATIC_CHECK(fuck_allowed_size_is_too_small,
(ACTUAL_SIZE > ALLOWED_SIZE));
}
ValidSizeConstraint()
{
void (*p)() = constraint;
(*p)();//call function, only to make compiler warning about unused variable go away, will get optimized away
}
};
/**
* static checks
* usage:
* struct B {}; struct D : B { };
* ...Derived_from<D,B>();
*/
template<class T, class B> struct Derived_from
{
static void constraints(T* p) { B* pb = p; pb = pb;}
Derived_from() { void(*p)(T*) = constraints; p = p;}
};
template<class T1, class T2> struct Can_copy
{
static void constraints(T1 a, T2 b) { T2 c = a; b = a; c = a; b = a; }
Can_copy() { void(*p)(T1,T2) = constraints;}
};
template<class T1, class T2 = T1> struct Can_compare
{
static void constraints(T1 a, T2 b) { a==b; a!=b; a<b; }
Can_compare() { void(*p)(T1,T2) = constraints;}
};
}//namespace common
#endif /*COMPILETIMECONSTRAINTS_H_*/

View File

@ -0,0 +1,175 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains STL like algorithms.
* \file SAlgorithm.h
* \ingroup sstl
*/
#ifndef SALGORITHM_H_
#define SALGORITHM_H_
#include "SIteratorBaseTypes.h"
/**
* returns minimum of two values
* \param T type of values
* \param t1 first value
* \param t2 second value
* \return minimum of t1 and t2
*/
template<typename T>
inline const T& smin(const T& t1, const T& t2)
{
return (t1 < t2 ? t1 : t2);
}
/**
* returns maximum of two values
* \param T type of values
* \param t1 first value
* \param t2 second value
* \return maximum of t1 and t2
*/
template<typename T>
inline const T& smax(const T& t1, const T& t2)
{
return (t1 > t2 ? t1 : t2);
}
/**
* swaps two values
* \param T type of values
* \param t1 first value
* \param t2 second value
*/
template<typename T>
inline void sswap(T& t1, T& t2)
{
T t = t1;
t1 = t2;
t2 = t;
}
/**
* finds a value in a given iterator range
* \param InputIterator type of iterators
* \param EqualityCompareable type of value to find
* \param first begin of range
* \param last and of range
* \param value value to find in range
* \return iterator to first element equal to value in range
*/
template<
typename InputIterator,
typename EqualityCompareable>
inline InputIterator sfind(
InputIterator first,
InputIterator last,
const EqualityCompareable& value)
{
return sfind(
first,
last,
value,
typename SIteratorTraits<InputIterator>::iterator_category());
}
/**
* implementation of sfind for input iterators
* \see sfind()
*/
template<
typename InputIterator,
typename EqualityCompareable>
inline InputIterator sfind(
InputIterator first,
InputIterator last,
const EqualityCompareable& value,
SInputIteratorTag)
{
while (!(first == last) && !(*first == value))
{
++first;
}
return first;
}
/**
* removes all elements equal to a value from a range and copies it to another
* \param InputIterator type of input range iterators
* \param OutputIterator type of result range iterator
* \param EqualityCompareable type of value to remove from input range
* \param first begin of input range
* \param last end of input range
* \param result begin iterator of result range
* \param value value to remove
* \return end of result range
*/
template<
typename InputIterator,
typename OutputIterator,
typename EqualityCompareable>
inline OutputIterator sremove_copy(
InputIterator first,
InputIterator last,
OutputIterator result,
const EqualityCompareable& value)
{
while (first != last)
{
if (!(*first == value))
{
*result = *first;
++result;
}
++first;
}
return result;
}
/**
* removes all elements of a given value from a range
* \param ForwardIterator type of range iterator
* \param EqualityCompareable type of value to remove
* \param first begin of range
* \param last end of range
* \param value value to remove from range
* \return iterator to result range
*/
template<
typename ForwardIterator,
typename EqualityCompareable>
ForwardIterator sremove(
ForwardIterator first,
ForwardIterator last,
const EqualityCompareable& value)
{
first = sfind(first, last, value);
ForwardIterator i = first;
return first == last ? first : sremove_copy(++i, last, first, value);
}
template<
typename InputIterator,
typename EqualityComparable>
typename SIteratorTraits<InputIterator>::difference_type scount(
InputIterator first, InputIterator last,
const EqualityComparable& value)
{
typename SIteratorTraits<InputIterator>::difference_type result = 0;
while (first != last)
{
if (*first == value)
{
++result;
}
++first;
}
return result;
}
#endif /*SALGORITHM_H_*/

View File

@ -0,0 +1,38 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains basic type traits.
* \file SBaseTypes.h
* \ingroup sstl
*/
#ifndef SBASETYPES_H_
#define SBASETYPES_H_
/**
* type traits
* \param T type to get traits from
*
* This class may be used to save some type work.
*/
template<typename T>
struct STypeTraits
{
/** unsigned integral type */
typedef unsigned int size_type;
/** signed integral type */
typedef signed int difference_type;
/** type of T itsself */
typedef T value_type;
/** pointer to T */
typedef T* pointer;
/** reference to T */
typedef T& reference;
/** const reference to T */
typedef const T& const_reference;
};
#endif /*SBASETYPES_H_*/

View File

@ -0,0 +1,141 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains base types for iterators.
* \file SIteratorBaseTypes.h
* \ingroup sstl
*/
#ifndef SITERATORBASETYPES_H_
#define SITERATORBASETYPES_H_
/**
* input iterator
*
* \section Description
* May advance through a iterator range. Reads each
* value exactly one time.
*/
struct SInputIteratorTag {};
/**
* output iterator
*
* \section Description
* May advance through a iterator range and alter values.
*/
struct SOutputIteratorTag {};
/**
* forward iterator
*
* \section Description
* May advance through a iterator range and read each value
* more than on time.
*/
struct SForwardIteratorTag : public SInputIteratorTag {};
/**
* bidirectional iterator
*
* \section Description
* May go through a iterator range in both directions and
* read each value more than one time
*/
struct SBidirectionalIteratorTag : public SForwardIteratorTag {};
/**
* random access iterator
*
* \section Description
* May go through a iterator range like a pointer through an
* array and read each value more than one time.
*/
struct SRandomAccessIteratorTag : public SBidirectionalIteratorTag {};
/**
* optional base class for iterators
* \param Category iterators category
* \param T type iterator points to
* \param Distance signed integral type
* \param Pointer pointer to T
* \param Reference reference to T
*
* Classes may subclass this class to save some typedef work.
*/
template<
typename Category,
typename T,
typename Distance = signed int,
typename Pointer = T*,
typename Reference = T&>
struct SIterator
{
/** the iterators category */
typedef Category iterator_category;
/** type of value iterator points to */
typedef T value_type;
/** signed integral type */
typedef Distance difference_type;
/** pointer to value type */
typedef Pointer pointer;
/** reference to value type */
typedef Reference reference;
};
/**
* traits for iterators
* \param Iterator iterator to generate traits for
*/
template<typename Iterator>
struct SIteratorTraits
{
/** the iterators category */
typedef typename Iterator::iterator_category iterator_category;
/** type of value iterator points to */
typedef typename Iterator::value_type value_type;
/** signed integral type */
typedef typename Iterator::difference_type difference_type;
/** pointer to value */
typedef typename Iterator::pointer pointer;
/** reference to value */
typedef typename Iterator::reference reference;
};
/**
* special implementation for pointers
* \param T type of value for whose pointer traits are generated
*
* \see SIteratorTraits
*/
template<typename T>
struct SIteratorTraits<T*>
{
typedef SRandomAccessIteratorTag iterator_category;
typedef T value_type;
typedef signed int difference_type;
typedef value_type* pointer;
typedef value_type& reference;
};
/**
* special implementation for const pointers
* \param T type of value for whose const pointer traits are generated
*
* \see SIteratorTraits
*
*/
template<typename T>
struct SIteratorTraits<const T*>
{
typedef SRandomAccessIteratorTag iterator_category;
typedef T value_type;
typedef signed int difference_type;
typedef const value_type* pointer;
typedef const value_type& reference;
};
#endif /*SITERATORBASETYPES_H_*/

View File

@ -0,0 +1,441 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef SLINKEDLIST_H_
#define SLINKEDLIST_H_
#include "util/SBaseTypes.h"
#include "util/SIteratorBaseTypes.h"
#include "util/CompileTimeConstraints.h"
#include <cassert>
template<typename T>
class SLinkedListSetNode
{
public:
typedef T value_type;
SLinkedListSetNode() :
fpNext(0L),
fAddedToList(false)
{}
T* getNext() const
{
return fpNext;
}
void setNext(T* pNext)
{
fpNext = pNext;
}
void addToList()
{
assert(!fAddedToList);
fAddedToList = true;
}
void removeFromList()
{
fAddedToList = false;
}
private:
SLinkedListSetNode(const SLinkedListSetNode&);
SLinkedListSetNode& operator=(const SLinkedListSetNode&);
T* fpNext;
bool fAddedToList;
};
template<typename T>
class SLinkedListSetIterator;
template<typename T>
class SLinkedListSet
: common::Derived_from<T, SLinkedListSetNode<T> >
{
private:
/** type of list itsself */
typedef SLinkedListSet<T> self_type;
public:
/** type of values stored in vector */
typedef typename STypeTraits<T>::value_type value_type;
/** pointer to value */
typedef typename STypeTraits<T>::pointer pointer;
/** reference to value */
typedef typename STypeTraits<T>::reference reference;
/** const reference to value */
typedef typename STypeTraits<T>::const_reference const_reference;
/** unsigned integral type */
typedef typename STypeTraits<T>::size_type size_type;
/** signed integral type */
typedef typename STypeTraits<T>::difference_type difference_type;
/** iterator type */
typedef SLinkedListSetIterator<T> iterator;
/** const iterator type */
typedef SLinkedListSetIterator<const T> const_iterator;
SLinkedListSet() :
fpFirst(0L),
fpLast(0L)
{
clear();
}
/**
* @note
* O(n)!
* @todo
* Maybe a field would be better
*/
size_type size() const
{
size_type size = (fpFirst) ? 1 : 0;
for (const T* pNode = fpFirst; pNode != fpLast; pNode = pNode->getNext())
{
++size;
}
return size;
}
bool empty() const
{
return (fpFirst == 0L);
}
void clear()
{
while (!empty())
{
pop_front();
}
fpFirst = 0L;
fpLast = 0L;
}
const_reference front() const
{
assert(fpFirst);
return *fpFirst;
}
reference front()
{
return const_cast<reference>(
static_cast<const self_type&>(
*this).front());
}
const_reference back() const
{
assert(fpLast);
return *fpLast;
}
reference back()
{
return const_cast<reference>(
static_cast<const self_type&>(
*this).back());
}
void push_front(T& node)
{
if (contains_node(&node))
{
return;
}
node.addToList();
node.setNext(fpFirst);
fpFirst = &node;
if (!fpLast)
{//inserted first node
fpLast = fpFirst;
fpFirst->setNext(0L);
}
}
void push_back(T& node)
{
if (empty())
{//inserted first node
fpFirst = &node;
}
else
{
if (contains_node(&node))
{
return;
}
fpLast->setNext(&node);
}
node.addToList();
fpLast = &node;
fpLast->setNext(0L);
}
void pop_front()
{
if (!fpFirst)
{
return;
}
fpFirst->removeFromList();
fpFirst = fpFirst->getNext();
if (!fpFirst)
{//removed last element
fpLast = 0L;
}
}
void pop_back();
iterator begin()
{
return iterator(fpFirst);
}
const_iterator begin() const
{
return const_iterator(fpFirst);
}
iterator end()
{
return iterator(0L);
}
const_iterator end() const
{
return const_iterator(0L);
}
iterator erase(iterator pos);
iterator insert(iterator pos, T& value);
void remove(const T& value);
bool contains(const T& value) const
{
return contains_node(&value);
}
private:
SLinkedListSet(const SLinkedListSet&);
SLinkedListSet& operator=(const SLinkedListSet&);
T* findPredecessor(const T* pNode) const
{
T* pResult = fpFirst;
while ((pResult != 0L) && (pResult->getNext() != pNode))
{
pResult = pResult->getNext();
}
return pResult;
}
bool contains_node(const T* pNodeToFind) const;
T* fpFirst;
T* fpLast;
};
template<typename T>
bool SLinkedListSet<T>::contains_node(const T* pNodeToFind) const
{
T* pNode = fpFirst;
while (pNode != 0L)
{
if (pNodeToFind == pNode)
{
return true;
}
pNode = pNode->getNext();
}
return false;
}
template<typename T>
void SLinkedListSet<T>::pop_back()
{
if (!fpLast)
{
return;
}
fpLast->removeFromList();
if (fpFirst == fpLast)
{
clear();
}
else
{
fpLast = findPredecessor(fpLast);
assert(fpLast);
fpLast->setNext(0L);
}
}
template<typename T>
typename SLinkedListSet<T>::iterator SLinkedListSet<T>::erase(
SLinkedListSet<T>::iterator pos)
{
if (!fpFirst)
{
return end();
}
iterator next = pos;
++next;
if (pos == begin())
{//remove first element
pop_front();
}
else
{
pos->removeFromList();
T* pNode = findPredecessor(pos.operator->());
assert(pNode);
if (pNode->getNext() == fpLast)
{//removing last element
fpLast = pNode;
}
pNode->setNext(pos->getNext());
}
return next;
}
template<typename T>
typename SLinkedListSet<T>::iterator SLinkedListSet<T>::insert(
SLinkedListSet<T>::iterator pos,
T& value)
{
if (contains_node(&value))
{
return pos;
}
if (empty() || (pos == begin()))
{
push_front(value);
}
else if (pos == end())
{
push_back(value);
}
else
{
value.addToList();
T* pNode = findPredecessor(pos.operator->());
assert(pNode);
value.setNext(pNode->getNext());
pNode->setNext(&value);
}
return iterator(&value);
}
template<typename T>
void SLinkedListSet<T>::remove(const T& value)
{
if (&value == fpFirst)
{
pop_front();
}
else if (&value == fpLast)
{
pop_back();
}
else
{
const_cast<T&>(value).removeFromList();
T* pNode = findPredecessor(&value);
if (pNode)
{
pNode->setNext(value.getNext());
}
}
}
template <typename T>
bool operator==(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y);
template <typename T>
bool operator!=(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y);
template<typename T>
class SLinkedListSetIterator
{
public:
/** the iterators category */
typedef SForwardIteratorTag iterator_category;
/** value type of iterator */
typedef typename STypeTraits<T>::value_type value_type;
/** reference to value */
typedef typename STypeTraits<T>::reference reference;
/** pointer to value */
typedef typename STypeTraits<T>::pointer pointer;
/** signed integral type */
typedef typename STypeTraits<T>::difference_type difference_type;
SLinkedListSetIterator(T* pValue) :
fpValue(pValue)
{}
SLinkedListSetIterator(const SLinkedListSetIterator& rhs) :
fpValue(rhs.fpValue)
{}
SLinkedListSetIterator& operator=(const SLinkedListSetIterator& rhs)
{
fpValue = rhs.fpValue;
return *this;
}
SLinkedListSetIterator& operator++()
{
fpValue = fpValue->getNext();
return *this;
}
reference operator*()
{
return *fpValue;
}
pointer operator->()
{
return fpValue;
}
private:
friend bool operator==<T>(
const SLinkedListSetIterator<T>&,
const SLinkedListSetIterator<T>&);
friend bool operator!=<T>(
const SLinkedListSetIterator<T>&,
const SLinkedListSetIterator<T>&);
T* fpValue;
};
template<typename T>
inline bool operator==(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y)
{
return (x.fpValue == y.fpValue);
}
template<typename T>
inline bool operator!=(
const SLinkedListSetIterator<T>& x,
const SLinkedListSetIterator<T>& y)
{
return !(x == y);
}
#endif /*SLINKEDLIST_H_*/

View File

@ -0,0 +1,57 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains helpers to make C++ classes uncopyable, i.e. declare copy
* constructor and assignment operator private.
* \file Uncopyable.h
*/
#ifndef UNCOPYABLE_H_
#define UNCOPYABLE_H_
/**
* The macro MAKE_UNCOPYABLE expands to a declaration of copy constructor and
* assignment operator.
* \par Usage example
* \code
* class MyClass
* {
* MAKE_UNCOPYABLE(MyClass)
* public:
* //...
* };
* \endcode
*/
#ifdef MAKE_UNCOPYABLE
#error "MAKE_UNCOPYABLE was already defined!"
#endif
// PRQA S 1030 3
#define MAKE_UNCOPYABLE(TypeName) \
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&);
namespace common
{
/**
* Inheriting from Uncopyable makes sure that no copies of any subclass
* are instantiated accidently because the C++ compiler will raise an error.
*
* \author oliver.mueller
*/
class Uncopyable
{
protected:
Uncopyable(){}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
}//namespace common
#endif /*UNCOPYABLE_H_*/

24
2015/ppc/gps/Project.meta Normal file
View File

@ -0,0 +1,24 @@
Project {
ExecutableConfig UnitTest {
Files "src/**/*.cpp"
ExcludeFiles "src/ac/*.cpp"
Files "test/**/*.cpp"
IncludeDir "include"
IncludeDir "test/include"
IncludeDir "common/include"
ArtifactName "gpsTests.exe"
PostSteps {
CommandLine "$(OutputDir)/$(ArtifactName) -r xml --out $(OutputDir)/test_$(ArtifactName).xml", filter: run, default: off
}
DefaultToolchain GCC {
Compiler CPP {
Flags "-g -Wall -fpermissive -fmessage-length=0"
Define "UNIT_TEST"
}
Compiler C {
Flags "-g -Wall -fpermissive -fmessage-length=0"
Define "UNIT_TEST"
}
}
}
}

View File

@ -0,0 +1,36 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef AC_PUSHER_H_
#define AC_PUSHER_H_
#include "gps/IACPusher.h"
namespace android
{
class ICaimTransceiver;
}
namespace gps
{
class GpsAcPusher : public IACPusher
{
public:
virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs);
private:
uint8 fPosition[15];
ICaimTransceiver& fCaimTransceiver;
static const uint8 LONGITUDE_OFFSET = 0;
static const uint8 LATITUDE_OFFSET = 4;
static const uint8 HEADING_OFFSET = 8;
static const uint8 HEIGHT_OFFSET = 9;
static const uint8 QUALITY_OFFSET = 11;
static const uint8 SPEED_OFFSET = 13;
};
} // namespace gps
#endif /* end of include guard */

View File

@ -0,0 +1,21 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef IAC_PUSHER_H_
#define IAC_PUSHER_H_
#include "commonTypes.h"
namespace gps
{
class IGpsACPusher
{
public:
virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs) = 0;
};
} // namespace gps
#endif /* end of include guard */

View File

@ -0,0 +1,236 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef BUSID_H_
#define BUSID_H_
#include "commonTypes.h"
#include "util/Uncopyable.h"
//forward declarations
class BusIdIterator;
/**
* Abstraction for bus ids used throughout the system.
* @author matthias.kessler
*
* BusId contains constants for all busses used and provides an iterator
* to access them. Each BusId will have an index that is unique in the system.
*/
class BusId
{
public:
enum { MAX_INDEX = 4 };
/** iterator over BusIds */
typedef BusIdIterator iterator;
/** maximum number of busses, used to allocate static memory */
static const uint8 MAX_NUMBER_OF_BUSSES = MAX_INDEX;
static const uint8 NUMBER_OF_LIN_BUSSES = 1;
static const BusId BODYCAN;
static const BusId LIN;
static const BusId TAS;
static const BusId SELFDIAG;
static const BusId INVALID; //MUST be last BusId and is not part of MAX_NUMBER_OF_BUSSES
/**
* constructor
* @param name string representation of BusId
*/
explicit BusId(const char* name);
/**
* @return the BusIds name
*/
const char* getName() const
{
return fpName;
}
/**
* @return the BusIds unique index
*/
uint8 toIndex() const
{
return fId;
}
uint8 toCANIndex() const;
uint8 toLINIndex() const;
/**
* @param index index of BusId to access
* @return BusId at given index
*/
static const BusId& get(uint8 index);
/**
* @return iterator to first BusId
*/
static iterator begin();
/**
* @return iterator one past last BusId
*/
static iterator end();
/**
* @return total number of busses (excluding INVALID)
*/
static uint8 numberOfBusses()
{
return sfIdCount;
}
private:
MAKE_UNCOPYABLE(BusId)
//friends
friend bool operator==(const BusId& x, const BusId& y);
friend bool operator!=(const BusId& x, const BusId& y);
friend class BusIdIterator;
//fields
uint8 fId;
const char* fpName;
//static fields
static uint8 sfIdCount;
static BusId* sfBusId[MAX_NUMBER_OF_BUSSES];
};
/**
* Compares two given BusIds
* @param x first BusId to compare
* @param y second BusId to compare
* @return
* - true BusIds are equal
* - false BusIds are not equal
*/
inline bool operator==(const BusId& x, const BusId& y)
{
return (x.fId == y.fId);
}
/**
* Compares two given BusIds
* @param x first BusId to compare
* @param y second BusId to compare
* @return
* - true BusIds are not equal
* - false BusIds are equal
*/
inline bool operator!=(const BusId& x, const BusId& y)
{
return (x.fId != y.fId);
}
/**
* Iterator for BusIds.
* @author matthias.kessler
*/
class BusIdIterator
{
public:
/** pointer to a BusId */
typedef BusId* pointer;
/** reference to a BusId */
typedef BusId& reference;
/**
* constructor
* @param pBusId pointer to BusId this iterator points initially to
*/
explicit BusIdIterator(BusId* pBusId) :
fpBusId(pBusId)
{}
/**
* copy constructor
* @param itr iterator to copy from
*/
BusIdIterator(const BusIdIterator& itr) :
fpBusId(itr.fpBusId)
{}
/**
* assignment operator
* @param itr iterator to copy from
*/
BusIdIterator& operator=(const BusIdIterator& itr)
{
if (&itr != this)
{
fpBusId = itr.fpBusId;
}
return *this;
}
/**
* @return pointer to BusId iterator currently points to
*/
pointer operator->() const
{
return fpBusId;
}
/**
* @return reference to BusId iterator currently points to
*/
reference operator*() const
{
return *fpBusId;
}
/**
* prefix increment operator
* @return next iterator
*/
BusIdIterator& operator++()
{
if (fpBusId->toIndex() < BusId::sfIdCount-2)//-2 because of INVALID is last BusId
{
fpBusId = BusId::sfBusId[fpBusId->toIndex() + 1];
}
else
{
fpBusId = 0L;
}
return *this;
}
private:
//friends
friend bool operator==(const BusIdIterator& x, const BusIdIterator& y);
friend bool operator!=(const BusIdIterator& x, const BusIdIterator& y);
//fields
BusId* fpBusId;
};
/**
* compares two BusIdIterators
* @param x first BusIdIterators to compare
* @param y second BusIdIterators to compare
* @return
* - true BusIdIterators are equal
* - false BusIdIterators are not equal
*/
inline bool operator==(const BusIdIterator& x, const BusIdIterator& y)
{
return (x.fpBusId == y.fpBusId);
}
/**
* compares two BusIdIterators
* @param x first BusIdIterators to compare
* @param y second BusIdIterators to compare
* @return
* - true BusIdIterators are not equal
* - false BusIdIterators are equal
*/
inline bool operator!=(const BusIdIterator& x, const BusIdIterator& y)
{
return (x.fpBusId != y.fpBusId);
}
#endif /*BUSID_H_*/

View File

@ -0,0 +1,18 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* @file BusIdMask.h
*/
#ifndef BUSIDMASK_H_
#define BUSIDMASK_H_
#include "util/Mask.h"
#include "busId/BusId.h"
typedef Mask<BusId, uint32> BusIdMask;
#endif /*BUSIDMASK_H_*/

View File

@ -0,0 +1,44 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef I_CAN_TRANSCEIVER_H_
#define I_CAN_TRANSCEIVER_H_
#include "can/canframes/CANFrame.h"
namespace can
{
class ICANTransceiver
{
public:
enum ErrorCode
{
CAN_ERR_OK,
CAN_ERR_TX_FAIL
};
virtual ErrorCode init() = 0;
virtual void shutdown() = 0;
virtual ErrorCode open() = 0;
virtual ErrorCode close() = 0;
virtual ErrorCode mute() = 0;
virtual ErrorCode unmute() = 0;
virtual ErrorCode write(const can::CANFrame& frame) = 0;
virtual uint32 getBaudrate() const = 0;
virtual uint16 getHwQueueTimeout() const = 0;
};
} // namespace can
#endif /* end of include guard */

View File

@ -0,0 +1,181 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains Cpp2CAN CANFrame.
* @file CANFrame.h
* @ingroup cpp2can
*/
#ifndef CANFRAME_H
#define CANFRAME_H
#include "commonTypes.h"
#include <cassert>
namespace can
{
/**
* Class representing a CANFrame.
* @author matthias.kessler
*
* A object of type CANFrame does not provide any payload-buffer by default.
* It has to be provided with buffers by using a certain constructor or the
* setPayload() method.
*
* @note
* CANFrame may be used as base class for special frame classes providing
* the programmer with explicit methods to access the signals that are
* encoded in the CANFrames payload.
*/
class CANFrame
{
public:
/** bitmask to extract sender */
static const uint8 SENDER_MASK = 0xFF;
/** overhead of a CANFrame (in bit) */
static const uint8 CAN_OVERHEAD_BITS = 47;
/** maximum payload length of a CANFrame */
static const uint8 MAX_FRAME_LENGTH = 8;
/** maximum value of a CANFrame id */
static const uint16 MAX_FRAME_ID = 0x7FF;
/**
* @post getId() == 0x00
* @post getPayload() == NULL
* @post getPayloadLength() == 0
* @post getTimestamp() == 0
*/
CANFrame();
/**
* Copy constructor
* @param frame CANFrame to copy content from
*/
CANFrame(const CANFrame& frame);
/**
* Constructor initializing id, payload and length
*
* @pre id <= MAX_FRAME_ID
* @pre length <= MAX_FRAME_LENGTH
* @throws assertion
*
* The payload will not be copied, it is passed as a
* reference and CANFrame will work on this payload!
*/
CANFrame(uint16 id, uint8 payload[], uint8 length);
uint16 getId() const
{
return fId;
}
void setId(uint16 id)
{
this->fId = id;
}
/**
* @return pointer to modifiable payload of this CANFrame
*/
uint8* getPayload()
{
return fpPayload;
}
/**
* @return pointer to read only payload of this CANFrame
*/
const uint8* getPayload() const
{
return fpPayload;
}
/**
* Sets the CANFrames payload and length
*
* @note
* This method just sets a pointer to the payload and does not copy it!
*
* @post getPayload() == payload
* @post getPayloadLength() == length
* @post getMaxPayloadLength() == length
*/
void setPayload(uint8 payload[], uint8 length)
{
fpPayload = payload;
fPayloadLength = length;
fMaxPayloadLength = length;
}
/**
* @pre getPayload() != NULL
* @pre length <= getMaxPayloadLength()
* @throws assertion
*/
void setPayloadLength(uint8 length);
uint8 getPayloadLength() const
{
return fPayloadLength;
}
uint8 getMaxPayloadLength() const
{
return fMaxPayloadLength;
}
/**
* Assigns content of a CANFrame to another.
* @param canFrame frame to copy from
* @return reference to frame with new content
* @pre getMaxPayloadLength() >= canFrame.getPayloadLength()
* @throws assertion
*/
CANFrame& operator=(const CANFrame& canFrame);
/**
* @return modifiable reference to timestamp
*/
uint64& getTimestamp()
{
return fTimestamp; // PRQA S 4024
}
/**
* @return read only access to timestamp
*/
const uint64& getTimestamp() const
{
return fTimestamp;
}
bool isExtended() const { return false; } /* TODO: cleanup */
protected:
friend bool operator==(const CANFrame& frame1, const CANFrame& frame2);
uint8* fpPayload;
uint16 fId;
uint8 fPayloadLength;
uint8 fMaxPayloadLength;
uint64 fTimestamp;
};
/**
* Compares two CANFrames without considering the timestamp
* @param frame1 first frame to compare
* @param frame2 second frame to compare
* @return
* - true if frames are equal
* - false if frames are not equal
*/
bool operator==(const CANFrame& frame1, const CANFrame& frame2);
} /* namespace can */
#endif /* CANFRAME_H */

View File

@ -0,0 +1,79 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains IFilter interface.
* @file IFilter.h
* @ingroup filter
*/
#ifndef IFILTER_H_
#define IFILTER_H_
#include "commonTypes.h"
#include "util/Uncopyable.h"
namespace can
{
//forward declaration
class IMerger;
/**
* common interface for filter classes
* @author matthias.kessler
*/
class IFilter
{
public:
IFilter() {};
/**
* adds a single id to the filter
* @param id id to add
* @post filter.match(id)
*/
virtual void add(uint16 id) = 0;
/**
* adds a range of ids to the filter
* @param from begin of range
* @param to end of range
* @post filter.match(from...to);
*/
virtual void add(uint16 from, uint16 to) = 0;
/**
* checks if a given id matches the filter
* @return
* - true: id matches filter
* - false: id does not match filter
*/
virtual bool match(uint16 id) const = 0;
/**
* clears the filter so that nothing matches
*/
virtual void clear() = 0;
/**
* opens the filters full range
*/
virtual void open() = 0;
/**
* merges filter with a given merger
* @param merger IMerger to merge filter to
*
* This is part of the visitor pattern that is used to
* merge different kinds of filters.
*/
virtual void acceptMerger(IMerger& merger) = 0;
private:
MAKE_UNCOPYABLE(IFilter)
};
} //namespace can
#endif /*IFILTER_H_*/

View File

@ -0,0 +1,62 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains IMerger interface.
* @file IMerger.h
* @ingroup filter
*/
#ifndef _IMERGER_H_
#define _IMERGER_H_
#include "util/Uncopyable.h"
namespace can
{
//forward declarations
class BitFieldFilter;
class AbstractStaticBitFieldFilter;
class IntervalFilter;
/**
* interface for class that are able to merge with other filter classes
* @class IMerger
* @author gerd.schaefer
*
* @see BitFieldFilter
* @see AbstractStaticBitFieldFilter
* @see IntervalFilter
*/
class IMerger
{
public:
IMerger() {}
/**
* merges with a BitFieldFilter
* @param filter BitFieldFilter to merge with
*/
virtual void mergeWithBitField(BitFieldFilter& filter) = 0;
/**
* merges with a AbstractStaticBitFieldFilter
* @param filter AbstractStaticBitFieldFilter to merge with
*/
virtual void mergeWithStaticBitField(AbstractStaticBitFieldFilter& filter) = 0;
/**
* merges with a IntervalFilter
* @param filter IntervalFilter to merge with
*/
virtual void mergeWithInterval(IntervalFilter& filter) = 0;
private:
MAKE_UNCOPYABLE(IMerger)
};
} //namespace can
#endif //_IMERGER_H_

View File

@ -0,0 +1,148 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains IntervalFilter class.
* @file IntervalFilter.h
* @ingroup filter
*/
#ifndef _INTERVALFILTER_H_
#define _INTERVALFILTER_H_
#include "commonTypes.h"
#include "can/canframes/CANFrame.h"
#include "can/filter/IFilter.h"
#include "can/filter/IMerger.h"
#include "util/Uncopyable.h"
namespace can
{
/**
* Cpp2CAN IntervalFilter
* @author gerd.schaefer, matthias.kessler
*
* @see IFilter
*/
class IntervalFilter :
public IFilter
{
public:
/** maximum id the filter may take */
static const uint16 MAX_ID = CANFrame::MAX_FRAME_ID;
/**
* constructor
* @post getLowerBound() == MAX_ID
* @post getUpperBound() == 0x0
*
* Nothing wil be accepted by default
*/
IntervalFilter();
/**
* constructor initializing an interval
* @param from first id that will be accepted
* @param to last id that will be accepted
* @pre from <= MAX_ID
* @pre to <= MAX_ID
* @post getLowerBound() == from
* @post getUpperBound() == to
*
* @note
* If from or to exceed MAX_ID, they will be set to MAX_ID.
*/
explicit IntervalFilter(uint16 from, uint16 to);
/**
* @see IFilter::add()
* @param id id to add to filter
* @pre id <= MAX_ID, otherwise no effect
* @post getLowerBound() == min(id, getLowerBound())
* @post getUpperBound() == max(id, getUpperBound())
*
* @note
* This call is equal to add(id, id).
*/
virtual void add(uint16 id)
{
if (id <= MAX_ID)
{
add(id, id);
}
}
/**
* @see IFilter::add()
* @param from lower bound of interval to add
* @param to upper bound of interval to add
* @pre from <= MAX_ID
* @pre to <= MAX_ID
* @post getLowerBound() == min(from, getLowerBound())
* @post getUpperBound() == max(to, getUpperBound())
*
* If from or to exceed MAX_ID, they will be set to MAX_ID.
*
* This call will not replace the current filter configuration, but
* adjust lower and upper bound of the filter according to the parameters.
*/
virtual void add(uint16 from, uint16 to);
/**
* checks if an id matches the filter
* @param id id to check
* @return
* - true: filter matches id
* - false: id is not in filters range
*/
virtual bool match(uint16 id) const
{
return (id >= fFrom) && (id <= fTo);
}
/**
* @see IFilter::acceptMerger()
*/
virtual void acceptMerger(IMerger& merger)
{
merger.mergeWithInterval(*this);
}
/**
* @see IFilter::clear();
*/
virtual void clear();
/**
* @see IFilter::open();
*/
virtual void open();
/**
* @return lower bound of filter
*/
uint16 getLowerBound() const
{
return fFrom;
}
/**
* @return upper bound of filter
*/
uint16 getUpperBound() const
{
return fTo;
}
private:
MAKE_UNCOPYABLE(IntervalFilter)
//fields
uint16 fFrom;
uint16 fTo;
};
} /*namespace can*/
#endif //_INTERVALFILTER_H_

View File

@ -0,0 +1,50 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
/**
* Contains interface ICANFrameListener.
* @file ICANFrameListener.h
* @ingroup framemgmt
*/
#ifndef ICANFRAMELISTENER_H
#define ICANFRAMELISTENER_H
#include "util/SLinkedListSet.h"
#include "util/Uncopyable.h"
namespace can
{
class CANFrame;
class IFilter;
/**
* CANFrameListener interface
* @author matthias.kessler
*
* An ICANFrameListener subclass is a class interested in the reception
* of CANFrames. Therefore it needs to register at an AbstractCANTransceiver.
*/
class ICANFrameListener :
public SLinkedListSetNode<ICANFrameListener>
{
MAKE_UNCOPYABLE(ICANFrameListener)
public:
ICANFrameListener() {}
/**
* This method notifies the listener of a CANFrame reception.
*/
virtual void frameReceived(const CANFrame& canFrame) = 0;
/**
* Returns the ICANFrameListeners filter.
*/
virtual IFilter& getFilter() = 0;
};
} //namespace can
#endif // ICANFRAMELISTENER_H

View File

@ -0,0 +1,48 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#ifndef GPSCONVERTER_H_
#define GPSCONVERTER_H_
#include "commonTypes.h"
#include "can/framemgmt/ICANFrameListener.h"
#include "can/filter/IntervalFilter.h"
namespace can
{
class CANFrame;
class ICANTransceiver;
}
namespace gps
{
class IGpsACPusher;
class GpsConverter :
public can::ICANFrameListener
{
public:
enum { GPS_FRAME_ID = 0x34a }; //NavGps1
GpsConverter(can::ICANTransceiver& transceiver, IGpsACPusher& acPusher);
/* ICANFrameListener */
virtual void frameReceived(const can::CANFrame& canFrame);
virtual can::IFilter& getFilter()
{
return fCanFilter;
}
private:
can::ICANTransceiver& fCanTransceiver;
can::IntervalFilter fCanFilter;
IGpsACPusher& fAcPusher;
sint32 fLastLatInMs;
sint32 fLastLongInMs;
};
} // namespace gps
#endif /* end of include guard */

7
2015/ppc/gps/rakefile.rb Normal file
View File

@ -0,0 +1,7 @@
desc "run unittests"
task :runTests do
sh "bake -b UnitTest -a black --include_filter run"
end
task :default => :run

View File

@ -0,0 +1,33 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#include "gps/AcPusher.h"
#include "android/caim/base/ICaimTransceiver.h"
#include "util/endian.h"
namespace gps
{
void GpsAcPusher::pushGPSCoordinates(sint32 latMs, sint32 longMs)
{
uint8 newPosition[sizeof(fPosition)];
writeMem32(newPosition + LONGITUDE_OFFSET, longMs);
writeMem32(newPosition + LATITUDE_OFFSET, latMs);
writeMem16(newPosition + HEIGHT_OFFSET, 0);
writeMem16(newPosition + SPEED_OFFSET, 0);
newPosition[HEADING_OFFSET] = 0;
writeMem16(newPosition + QUALITY_OFFSET, 0);
if (memcmp(newPosition, fPosition, sizeof(fPosition)))
{
memcpy(fPosition, newPosition, sizeof(fPosition));
fCaimTransceiver.push(POSITION_COMMAND, fPosition, sizeof(fPosition));
}
}
} // namespace gps

View File

@ -0,0 +1,99 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#include "can/canframes/CANFrame.h"
namespace can
{
//define const variables for GCC
#ifdef __GNUC__
const uint8 CANFrame::SENDER_MASK;
const uint8 CANFrame::CAN_OVERHEAD_BITS;
const uint8 CANFrame::MAX_FRAME_LENGTH;
const uint16 CANFrame::MAX_FRAME_ID;
#endif
CANFrame::CANFrame() :
fpPayload(0L),
fId(0),
fPayloadLength(0),
fMaxPayloadLength(0),
fTimestamp(0)
{}
CANFrame::CANFrame(const CANFrame& frame) :
fpPayload(frame.fpPayload),
fId(frame.fId),
fPayloadLength(frame.fPayloadLength),
fMaxPayloadLength(frame.fMaxPayloadLength),
fTimestamp(frame.fTimestamp)
{
}
CANFrame::CANFrame(uint16 id, uint8 payload[], uint8 length) :
fpPayload(payload),
fId(id),
fPayloadLength(length),
fMaxPayloadLength(length)
{
assert(id <= MAX_FRAME_ID);
assert(length <= MAX_FRAME_LENGTH);
}
CANFrame& CANFrame::operator=(const CANFrame& canFrame)
{
if (&canFrame != this)
{
if (fMaxPayloadLength < canFrame.fPayloadLength)
{
assert(fMaxPayloadLength >= canFrame.fPayloadLength);
}
fId = canFrame.fId;
for (uint8 i = 0; i < canFrame.fPayloadLength; ++i)
{
fpPayload[i] = canFrame.fpPayload[i];
}
fPayloadLength = canFrame.fPayloadLength;
fTimestamp = canFrame.fTimestamp;
}
return *this;
}
void CANFrame::setPayloadLength(uint8 length)
{
if (!fpPayload)
{
assert(fpPayload != 0L);
}
if (length > fMaxPayloadLength)
{
assert(length <= fMaxPayloadLength);
}
fPayloadLength = length;
}
bool operator==(const CANFrame& frame1, const CANFrame& frame2)
{
if (frame1.fId != frame2.fId)
{
return false;
}
if (frame1.fPayloadLength != frame2.fPayloadLength)
{
return false;
}
for (uint8 i = 0; i < frame1.fPayloadLength; i++)
{
if (frame1.fpPayload[i] != frame2.fpPayload[i])
{
return false;
}
}
return true;
}
} //namespace can

View File

@ -0,0 +1,69 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#include "can/filter/IntervalFilter.h"
#include "util/SAlgorithm.h"
namespace can
{
#ifdef __GNUC__
const uint16 IntervalFilter::MAX_ID;
#endif
IntervalFilter::IntervalFilter()
{
clear();
}
IntervalFilter::IntervalFilter(uint16 from, uint16 to) :
fFrom(from),
fTo(to)
{
if (from > MAX_ID)
{
fFrom = MAX_ID;
}
if (to > MAX_ID)
{
fTo = MAX_ID;
}
}
void IntervalFilter::add(uint16 from, uint16 to)
{
if (from > MAX_ID)
{
from = MAX_ID;
}
if (to > MAX_ID)
{
to = MAX_ID;
}
//assert order
if (from > to)
{
sswap(from, to);
}
//adjust lower bound
fFrom = smin(fFrom, from);
//adjust upper bound
fTo = smax(fTo, to);
}
void IntervalFilter::clear()
{
fFrom = MAX_ID;
fTo = 0;
}
void IntervalFilter::open()
{
fFrom = 0x0;
fTo = MAX_ID;
}
} /*namespace can*/

View File

@ -0,0 +1,36 @@
/**
* \copyright
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
* All rights reserved.
*/
#include "gps/GpsConverter.h"
#include "ac/IGpsACPusher.h"
#include "can/canframes/CANFrame.h"
#include "can/ICANTransceiver.h"
#include <stdio.h>
using namespace can;
namespace gps
{
GpsConverter::GpsConverter(
ICANTransceiver& transceiver,
IGpsACPusher& acPusher)
: fCanTransceiver(transceiver)
, fCanFilter(GPS_FRAME_ID, GPS_FRAME_ID)
, fAcPusher(acPusher)
{
}
void GpsConverter::frameReceived(const CANFrame& canFrame)
{
const uint8* payload = canFrame.getPayload();
// TOOD implement conversion to arc-msec and call IGpsACPusher
}
} // namespace gps

View File

@ -0,0 +1,53 @@
#ifndef CANTRANSCEIVER_MOCK_H_
#define CANTRANSCEIVER_MOCK_H_
#include "can/ICANTransceiver.h"
#include "busId/BusId.h"
namespace can
{
class CanTransceiverMock
: public ICANTransceiver
{
public:
CanTransceiverMock()
{}
virtual ErrorCode init()
{
return CAN_ERR_OK;
}
virtual void shutdown() {}
virtual ErrorCode open()
{
return CAN_ERR_OK;
}
virtual ErrorCode close()
{
return CAN_ERR_OK;
}
virtual ErrorCode mute()
{
return CAN_ERR_OK;
}
virtual ErrorCode unmute()
{
return CAN_ERR_OK;
}
virtual ErrorCode write(const can::CANFrame& frame)
{
return CAN_ERR_OK;
}
virtual uint32 getBaudrate() const
{
return 500000;
}
virtual uint16 getHwQueueTimeout() const
{
return 50;
}
};
} // namespace can
#endif /* end of include guard */

View File

@ -0,0 +1,110 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "commonTypes.h"
#include "can/canframes/CANFrame.h"
#include "gps/GpsConverter.h"
#include "ac/IGpsACPusher.h"
#include "CanTransceiverMock.h"
#include "busId/BusId.h"
using namespace gps;
using namespace common;
using namespace can;
namespace test
{
class GpsAcPusherMock : public gps::IGpsACPusher
{
public:
GpsAcPusherMock()
: gpsWasSet(false)
{}
virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs)
{
printf("pushGPSCoordinates received: %d and %d\n", latMs, longMs);
gpsWasSet = true;
latitudeMs = latMs;
longitudeMs = longMs;
}
void clear()
{
gpsWasSet = false;
latitudeMs = 0;
longitudeMs = 0;
}
sint32 latitudeMs;
sint32 longitudeMs;
bool gpsWasSet;
};
class GpsConverterTest
{
public:
GpsConverterTest()
: canTransceiverMock()
, converter(canTransceiverMock, acPusherMock)
{}
virtual ~GpsConverterTest() {}
can::CanTransceiverMock canTransceiverMock;
GpsAcPusherMock acPusherMock;
GpsConverter converter;
};
static bool withinTolerance(sint32 x1, sint32 x2, sint32 tolerance)
{
return abs(x1-x2) < tolerance;
}
TEST_CASE_METHOD(GpsConverterTest, "london east calling", "[gps]")
{
uint8 payload[8] = { 0xDF, 0x48, 0xEA, 0xFF, 0x08, 0xC5, 0xA5, 0x24 };
CANFrame gpsInfo(0x34a, payload, 8);
converter.frameReceived(gpsInfo);
CHECK(acPusherMock.gpsWasSet);
CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
CHECK(withinTolerance(acPusherMock.longitudeMs, -429429, 100));
}
TEST_CASE_METHOD(GpsConverterTest, "london west calling", "[gps]")
{
uint8 payload[8] = { 0x1F, 0xB7, 0x15, 0x00, 0x08, 0xC5, 0xA5, 0x24 };
CANFrame gpsInfo(0x34a, payload, 8);
converter.frameReceived(gpsInfo);
SECTION("receive once")
{
CHECK(acPusherMock.gpsWasSet);
CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
CHECK(withinTolerance(acPusherMock.longitudeMs, 429428, 100));
}
SECTION("receive twice same value, only propagate once")
{
CHECK(acPusherMock.gpsWasSet);
CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
CHECK(withinTolerance(acPusherMock.longitudeMs, 429428, 100));
acPusherMock.clear();
converter.frameReceived(gpsInfo);
CHECK(!acPusherMock.gpsWasSet);
}
}
TEST_CASE_METHOD(GpsConverterTest, "invalid data", "[gps]")
{
uint8 payload[8] = { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80 };
CANFrame gpsInfo(0x34a, payload, 8);
converter.frameReceived(gpsInfo);
CHECK(!acPusherMock.gpsWasSet);
}
TEST_CASE_METHOD(GpsConverterTest, "no signal", "[gps]")
{
uint8 payload[8] = { 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F };
CANFrame gpsInfo(0x34a, payload, 8);
converter.frameReceived(gpsInfo);
CHECK(!acPusherMock.gpsWasSet);
}
// 48.1172966,11.5913253
// 48.1173275,11.591452
} // namespace test

9427
2015/ppc/gps/test/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

15
2015/ppc/rakefile.rb Normal file
View File

@ -0,0 +1,15 @@
desc "build"
task :build do
sh "bake -m gps -b UnitTest -a black"
end
desc "run"
task :run => :build do
sh "./gps/UnitTest/gpsTests.exe"
end
desc "clean"
task :clean do
sh "bake -m gps -b UnitTest -a black -c"
end