Skip to content

Commit efbed54

Browse files
Merge pull request FabioBatSilva#37 from nerdyscout/SPIFake
Spi fake
2 parents 0da2687 + 55505fb commit efbed54

File tree

10 files changed

+215
-0
lines changed

10 files changed

+215
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@
1010
**/Makefile
1111
!/Makefile
1212
/Testing/*
13+
.pio/*
14+
.vscode/*

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ cmake-test: build test
2626
clean:
2727
@rm -rf $(CURDIR)/build/*
2828
@rm -rf $(CURDIR)/.pioenvs/*
29+
@rm -rf $(CURDIR)/.pio/*

platformio.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[env:native]
22
platform = native
33
build_flags = -std=gnu++11
4+
test_build_src = yes

src/ArduinoFake.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "WireFake.h"
1919
#include "ClientFake.h"
2020
#include "PrintFake.h"
21+
#include "SPIFake.h"
2122

2223
#define ArduinoFake(mock) _ArduinoFakeGet##mock()
2324

@@ -36,6 +37,7 @@
3637
#define _ArduinoFakeGetFunction() _ArduinoFakeGetMock(Function)
3738
#define _ArduinoFakeGetSerial() _ArduinoFakeGetMock(Serial)
3839
#define _ArduinoFakeGetWire() _ArduinoFakeGetMock(Wire)
40+
#define _ArduinoFakeGetSPI() _ArduinoFakeGetMock(SPI)
3941
#define _ArduinoFakeGetStream() _ArduinoFakeGetMock(Stream)
4042
#define _ArduinoFakeGetClient() _ArduinoFakeGetMock(Client)
4143
#define _ArduinoFakeGetPrint() _ArduinoFakeGetMock(Print)
@@ -70,6 +72,7 @@ struct ArduinoFakeMocks
7072
fakeit::Mock<StreamFake> Stream;
7173
fakeit::Mock<ClientFake> Client;
7274
fakeit::Mock<PrintFake> Print;
75+
fakeit::Mock<SPIFake> SPI;
7376
};
7477

7578
struct ArduinoFakeInstances
@@ -80,6 +83,7 @@ struct ArduinoFakeInstances
8083
StreamFake* Stream;
8184
ClientFake* Client;
8285
PrintFake* Print;
86+
SPIFake* SPI;
8387
};
8488

8589
class ArduinoFakeContext
@@ -95,12 +99,14 @@ class ArduinoFakeContext
9599
_ArduinoFakeInstanceGetter1(Wire)
96100
_ArduinoFakeInstanceGetter1(Client)
97101
_ArduinoFakeInstanceGetter1(Function)
102+
_ArduinoFakeInstanceGetter1(SPI)
98103

99104
_ArduinoFakeInstanceGetter2(Print, Print)
100105
_ArduinoFakeInstanceGetter2(Client, Client)
101106
_ArduinoFakeInstanceGetter2(Stream, Stream)
102107
_ArduinoFakeInstanceGetter2(Serial, Serial_)
103108
_ArduinoFakeInstanceGetter2(Wire, TwoWire)
109+
_ArduinoFakeInstanceGetter2(SPI, SPIClass)
104110

105111
ArduinoFakeContext()
106112
{
@@ -117,9 +123,11 @@ class ArduinoFakeContext
117123
this->Mocks->Wire.Reset();
118124
this->Mocks->Client.Reset();
119125
this->Mocks->Print.Reset();
126+
this->Mocks->SPI.Reset();
120127

121128
Mapping[&::Serial] = this->Serial();
122129
Mapping[&::Wire] = this->Wire();
130+
Mapping[&::SPI] = this->SPI();
123131
}
124132
};
125133

src/SPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "SPIFake.h"

src/SPIFake.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "ArduinoFake.h"
2+
#include "SPIFake.h"
3+
4+
void SPIClass::begin() { ArduinoFakeInstance(SPI)->begin(); };
5+
6+
void SPIClass::end() { ArduinoFakeInstance(SPI)->end(); };
7+
8+
void SPIClass::beginTransaction(SPISettings settings) {
9+
ArduinoFakeInstance(SPI)->beginTransaction(settings);
10+
};
11+
12+
void SPIClass::endTransaction(void) {
13+
ArduinoFakeInstance(SPI)->endTransaction();
14+
};
15+
16+
uint8_t SPIClass::transfer(uint8_t data) {
17+
return ArduinoFakeInstance(SPI)->transfer(data);
18+
};
19+
20+
void SPIClass::transfer(void *buf, size_t count) {
21+
return ArduinoFakeInstance(SPI)->transfer(buf, count);
22+
};
23+
24+
SPIClass SPI = SPIFakeProxy(ArduinoFakeInstance(SPI));

src/SPIFake.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include "ArduinoFake.h"
4+
#include "arduino/SPI.h"
5+
6+
struct SPIFake {
7+
virtual uint8_t transfer(uint8_t data) = 0;
8+
virtual void transfer(void *buf, size_t count) = 0;
9+
10+
virtual void beginTransaction(SPISettings settings) = 0;
11+
virtual void endTransaction(void) = 0;
12+
13+
virtual void begin() = 0;
14+
virtual void end() = 0;
15+
};
16+
17+
class SPIFakeProxy : public SPIClass {
18+
private:
19+
SPIFake *spiFake;
20+
21+
public:
22+
SPIFakeProxy(SPIFake *fake) { spiFake = fake; }
23+
24+
SPIFake *getSPIFake() { return spiFake; }
25+
};

src/arduino/SPI.h

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
3+
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
4+
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
5+
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
6+
* SPI Master library for arduino.
7+
*
8+
* This file is free software; you can redistribute it and/or modify
9+
* it under the terms of either the GNU General Public License version 2
10+
* or the GNU Lesser General Public License version 2.1, both as
11+
* published by the Free Software Foundation.
12+
*/
13+
14+
#pragma once
15+
#include <stdint.h>
16+
#include <stdlib.h>
17+
#include <sys/types.h>
18+
19+
// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
20+
// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
21+
#define SPI_HAS_TRANSACTION 1
22+
23+
// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method
24+
#define SPI_HAS_NOTUSINGINTERRUPT 1
25+
26+
// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version.
27+
// This way when there is a bug fix you can check this define to alert users
28+
// of your code if it uses better version of this library.
29+
// This also implies everything that SPI_HAS_TRANSACTION as documented above is
30+
// available too.
31+
#define SPI_ATOMIC_VERSION 1
32+
33+
// Uncomment this line to add detection of mismatched begin/end transactions.
34+
// A mismatch occurs if other libraries fail to use SPI.endTransaction() for
35+
// each SPI.beginTransaction(). Connect an LED to this pin. The LED will turn
36+
// on if any mismatch is ever detected.
37+
// #define SPI_TRANSACTION_MISMATCH_LED 5
38+
39+
#ifndef LSBFIRST
40+
#define LSBFIRST 0
41+
#endif
42+
#ifndef MSBFIRST
43+
#define MSBFIRST 1
44+
#endif
45+
46+
#define SPI_CLOCK_DIV4 0x00
47+
#define SPI_CLOCK_DIV16 0x01
48+
#define SPI_CLOCK_DIV64 0x02
49+
#define SPI_CLOCK_DIV128 0x03
50+
#define SPI_CLOCK_DIV2 0x04
51+
#define SPI_CLOCK_DIV8 0x05
52+
#define SPI_CLOCK_DIV32 0x06
53+
54+
#define SPI_MODE0 0x00
55+
#define SPI_MODE1 0x04
56+
#define SPI_MODE2 0x08
57+
#define SPI_MODE3 0x0C
58+
59+
#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
60+
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
61+
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
62+
63+
// define SPI_AVR_EIMSK for AVR boards with external interrupt pins
64+
#if defined(EIMSK)
65+
#define SPI_AVR_EIMSK EIMSK
66+
#elif defined(GICR)
67+
#define SPI_AVR_EIMSK GICR
68+
#elif defined(GIMSK)
69+
#define SPI_AVR_EIMSK GIMSK
70+
#endif
71+
72+
class SPISettings {
73+
private:
74+
uint32_t clock;
75+
uint8_t bitOrder;
76+
uint8_t dataMode;
77+
78+
public:
79+
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode): clock(clock), bitOrder(bitOrder), dataMode(dataMode) {}
80+
SPISettings() { SPISettings(4000000, MSBFIRST, SPI_MODE0); }
81+
friend class SPIClass;
82+
83+
bool operator==(const SPISettings &other) const {
84+
return (clock == other.clock) && (bitOrder == other.bitOrder) &&
85+
(dataMode == other.dataMode);
86+
}
87+
};
88+
89+
class SPIClass {
90+
public:
91+
// Initialize the SPI library
92+
virtual void begin();
93+
virtual void end();
94+
95+
// Before using SPI.transfer() or asserting chip select pins,
96+
// this function is used to gain exclusive access to the SPI bus
97+
// and configure the correct settings.
98+
virtual void beginTransaction(SPISettings settings);
99+
100+
// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
101+
virtual uint8_t transfer(uint8_t data);
102+
virtual void transfer(void *buf, size_t count);
103+
104+
// After performing a group of transfers and releasing the chip select
105+
// signal, this function allows others to access the SPI bus
106+
virtual void endTransaction(void);
107+
108+
// virtual ~SPIClass();
109+
110+
private:
111+
};
112+
113+
extern SPIClass SPI;

test/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ using namespace fakeit;
1010
#include "test_stream.h"
1111
#include "test_serial.h"
1212
#include "test_wire.h"
13+
#include "test_spi.h"
1314
#include "test_client.h"
1415
#include "test_arduino_string.h"
1516
#include "test_include.h"
@@ -38,6 +39,7 @@ int main(int argc, char **argv)
3839
RUN_TEST_GROUP(StreamTest);
3940
RUN_TEST_GROUP(SerialTest);
4041
RUN_TEST_GROUP(WireTest);
42+
RUN_TEST_GROUP(SpiTest);
4143
RUN_TEST_GROUP(ClientTest);
4244
RUN_TEST_GROUP(IncludeTest);
4345

test/test_spi.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifdef UNIT_TEST
2+
3+
namespace SpiTest {
4+
5+
#include "arduino/SPI.h"
6+
7+
void test_basics(void) {
8+
SPISettings settings(4000000, MSBFIRST, SPI_MODE0);
9+
uint8_t data = 0x01;
10+
uint8_t buffer[] = {0x02, 0x03, 0x04};
11+
uint8_t *ptr = buffer;
12+
13+
When(OverloadedMethod(ArduinoFake(SPI), begin, void(void))).AlwaysReturn();
14+
When(OverloadedMethod(ArduinoFake(SPI), end, void(void))).AlwaysReturn();
15+
When(OverloadedMethod(ArduinoFake(SPI), beginTransaction, void(SPISettings)).Using(settings)).AlwaysReturn();
16+
When(OverloadedMethod(ArduinoFake(SPI), endTransaction, void(void))).AlwaysReturn();
17+
When(OverloadedMethod(ArduinoFake(SPI), transfer, uint8_t(uint8_t)).Using(data)).AlwaysReturn();
18+
When(OverloadedMethod(ArduinoFake(SPI), transfer, void(void*, size_t)).Using(ptr, sizeof(buffer))).AlwaysReturn();
19+
20+
SPI.begin();
21+
SPI.beginTransaction(settings);
22+
SPI.transfer(data);
23+
SPI.transfer(buffer, sizeof(buffer));
24+
SPI.endTransaction();
25+
SPI.end();
26+
27+
Verify(OverloadedMethod(ArduinoFake(SPI), begin, void(void))).Once();
28+
Verify(OverloadedMethod(ArduinoFake(SPI), end, void(void))).Once();
29+
Verify(OverloadedMethod(ArduinoFake(SPI), beginTransaction, void(SPISettings))).Once();
30+
Verify(OverloadedMethod(ArduinoFake(SPI), endTransaction, void(void))).Once();
31+
Verify(OverloadedMethod(ArduinoFake(SPI), transfer, uint8_t(uint8_t))).Once();
32+
Verify(OverloadedMethod(ArduinoFake(SPI), transfer, void(void*, size_t))).Once();
33+
}
34+
35+
void run_tests() { RUN_TEST(SpiTest::test_basics); }
36+
} // namespace SpiTest
37+
38+
#endif

0 commit comments

Comments
 (0)