aboutsummaryrefslogtreecommitdiffstats
path: root/vex/vexspi.cpp
blob: 4d05b9e34db90020fb437d305b5fc23f72cfd53f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*                        Copyright (c) James Pearman                          */
/*                                   2013                                      */
/*                            All Rights Reserved                              */
/*                                                                             */
/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*    Module:     vexspi.c                                                     */
/*    Author:     James Pearman                                                */
/*    Created:    7 May 2013                                                   */
/*                                                                             */
/*    Revisions:                                                               */
/*                V1.00     4 July 2013 - Initial release                      */
/*                                                                             */
/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*    This file is part of ConVEX.                                             */
/*                                                                             */
/*    The author is supplying this software for use with the VEX cortex        */
/*    control system. ConVEX is free software; you can redistribute it         */
/*    and/or modify it under the terms of the GNU General Public License       */
/*    as published by the Free Software Foundation; either version 3 of        */
/*    the License, or (at your option) any later version.                      */
/*                                                                             */
/*    ConVEX is distributed in the hope that it will be useful,                */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of           */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
/*    GNU General Public License for more details.                             */
/*                                                                             */
/*    You should have received a copy of the GNU General Public License        */
/*    along with this program.  If not, see <http://www.gnu.org/licenses/>.    */
/*                                                                             */
/*    A special exception to the GPL can be applied should you wish to         */
/*    distribute a combined work that includes ConVEX, without being obliged   */
/*    to provide the source code for any proprietary components.               */
/*    See the file exception.txt for full details of how and when the          */
/*    exception can be applied.                                                */
/*                                                                             */
/*    The author can be contacted on the vex forums as jpearman                */
/*    or electronic mail using jbpearman_at_mac_dot_com                        */
/*    Mentor for team 8888 RoboLancers, Pasadena CA.                           */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

#include "ch.h"         // needs for all ChibiOS programs
#include "hal.h"        // hardware abstraction layer header

#include <vex/vexspi.h>
#include <library.hpp>

SpiData vexSpiData; // externed in main.cpp

constexpr GPTDriver *spiGpt = &GPTD2;
constexpr const char *spiTeamName = CONVEX_TEAM_NAME;

static thread_t *spiThread = nullptr;

static SPIConfig spicfg = {
    nullptr,
    /* HW dependent part.*/
    VEX_SPI_CS_PORT, VEX_SPI_CS_PIN,
    SPI_CR1_DFF | SPI_CR1_BR_2 | SPI_CR1_CPHA
};

static void _vspi_gpt_cb(GPTDriver *);
static const GPTConfig vexSpiGpt = {
	1000000,      /* 1MHz timer clock.*/
	_vspi_gpt_cb, /* Timer callback.*/
	0,            /* DIER = 0, version 2.6.1.and on */
	0
};

static const unsigned char txInitData[32] = {
	0x17, 0xC9, 0x02, 0x00, 0x00, 0x00,
	0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x01, 0x00
};

static void _vspi_gpt_cb(GPTDriver *gptp)
{
	(void)gptp;

	chSysLockFromISR();
	if (spiThread != nullptr) {
		chSchReadyI(spiThread);
		spiThread = nullptr;
	}
	chSysUnlockFromISR();
}

void vexSpiTickDelay(int ticks)
{
	chSysLock();
	spiThread = chThdGetSelfX();
	gptStartOneShotI(spiGpt, ticks);
	chSchGoSleepS(CH_STATE_SUSPENDED);
	chSysUnlock();
}



namespace spi {
	void init(void) {
		memncpy(&vexSpiData.txdata, txInitData, 32);
		vexSpiData.online = 0;

		spiStart(&SPID1, &spicfg);
		gptStart(spiGpt, &vexSpiGpt);
	}


	void update(void) {
		auto txbuf = reinterpret_cast<uint16_t *>(vexSpiData.txdata.data);
		auto rxbuf = reinterpret_cast<uint16_t *>(vexSpiData.rxdata_t.data);

		// configure team name
		if (vexSpiData.txdata.pak.state == 0x03) {
			// let spi know what we're sending
			vexSpiData.txdata.pak.type = 0x55;
			strncpy(reinterpret_cast<char *>(vexSpiData.txdata.data + 6), spiTeamName, 8);
		}

	    // Set handshake to indicate new spi message
	    palSetPad(VEX_SPI_ENABLE_PORT, VEX_SPI_ENABLE_PIN);

	    for (int i = 0; i < 16; i++) {
			// exchange word (int)
	        spiSelectI(&SPID1);
	        rxbuf[i] = spi_lld_polled_exchange( &SPID1, txbuf[i] );
	        spiUnselectI(&SPID1);

			if (((i%4) == 3) && (i != 15)) {
	            // long delay between each group of 4 words
	            vexSpiTickDelay(73);

	            // After 4 words negate handshake pin
	            palClearPad(VEX_SPI_ENABLE_PORT, VEX_SPI_ENABLE_PIN);
	        } else {
	        	vexSpiTickDelay(8);
			}
	    }

	    // increase id for next message
	    vexSpiData.txdata.pak.id++;

	    // check integrity of received data
	    if( (vexSpiData.rxdata_t.data[0] == 0x17 ) && (vexSpiData.rxdata_t.data[1] == 0xC9 ))
	        {
	        // copy temporary data
	        for(int i=0;i<32;i++)
	            vexSpiData.rxdata.data[i] = vexSpiData.rxdata_t.data[i];

	        // Set online status if valid data status set
	        if( (vexSpiData.rxdata.pak.status & 0x0F) == 0x08 )
    	        vexSpiData.online = 1;

        	// If in configuration initialize state (0x02 or 0x03)
	        if( (vexSpiData.txdata.pak.state & 0x0E) == 0x02 )
	            {
	            // check for configure request
	            if( (vexSpiData.rxdata.pak.status & 0x0F) == 0x02 )
	                vexSpiData.txdata.pak.state = 0x03;
	            // check for configure and acknowledge
	            if( (vexSpiData.rxdata.pak.status & 0x0F) == 0x03 )
	                {
	                vexSpiData.txdata.pak.state = 0x08;
	                vexSpiData.txdata.pak.type  = 0;
	                }
	            // Either good or bad data force to normal transmission
	            // status will either be 0x04 or 0x08
	            if( (vexSpiData.rxdata.pak.status & 0x0C) != 0x00 )
	                {
	                vexSpiData.txdata.pak.state = 0x08;
	                vexSpiData.txdata.pak.type  = 0;
	                }
    	        }
	        }
	    else
	        vexSpiData.errors++;
	}

	void setMotors(uint8_t *data) {
		memncpy(data, vexSpiData.txdata.pak.motor, 8);
	}

	const jsdata& getJoystick(int num) {
		return (num == 2) ? vexSpiData.rxdata.pak.js_2 : vexSpiData.rxdata.pak.js_1;
	}

	int getBatteryMain(void) {
		return vexSpiData.rxdata.pak.batt1 * 59; // in mV
	}

	int getBatteryBackup(void) {
		return vexSpiData.rxdata.pak.batt2 * 59; 
	}

}