Welcome to mirror list, hosted at ThFree Co, Russian Federation.

PortControl.cpp « src - github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4a3c98fab6bc5b3b4d60a7bc6fae47ecbb2a9cdd (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
/*
 * PortControl.cpp
 *
 *  Created on: 15 Jun 2017
 *      Author: David
 */

#include "PortControl.h"
#include "GCodes/GCodeBuffer/GCodeBuffer.h"
#include "Movement/Move.h"
#include "Movement/DDA.h"
#include "Movement/StepTimer.h"

#if SUPPORT_IOBITS

PortControl::PortControl()
{
}

void PortControl::Init()
{
	numConfiguredPorts = 0;
	advanceMillis = 0;
	advanceClocks = 0;
	currentPortState = 0;
}

void PortControl::Exit()
{
	UpdatePorts(0);
	numConfiguredPorts = 0;
}

// Update the IO bits. Return the number of milliseconds before we need to be called again, or 0 to be called when movement restarts.
uint32_t PortControl::UpdatePorts()
{
	if (numConfiguredPorts == 0)
	{
		return 0;
	}

	SetBasePriority(NvicPriorityStep);
	const DDA * cdda = reprap.GetMove().GetMainDDARing().GetCurrentDDA();
	if (cdda == nullptr)
	{
		// Movement has stopped, so turn all ports off
		SetBasePriority(0);
		UpdatePorts(0);
		return 0;
	}

	// Find the DDA whose IO port bits we should set now
	const uint32_t now = StepTimer::GetTimerTicks() + advanceClocks;
	uint32_t moveEndTime = cdda->GetMoveStartTime();
	DDA::DDAState st = cdda->GetState();
	do
	{
		moveEndTime += cdda->GetClocksNeeded();
		if ((int32_t)(moveEndTime - now) >= 0)
		{
			SetBasePriority(0);
			UpdatePorts(cdda->GetIoBits());
			return (moveEndTime - now + StepTimer::StepClockRate/1000 - 1)/(StepTimer::StepClockRate/1000);
		}
		cdda = cdda->GetNext();
		st = cdda->GetState();
	} while (st == DDA::executing || st == DDA::frozen);

	SetBasePriority(0);
	UpdatePorts(0);
	return 0;
}

// Set up the GPIO ports returning true if error
bool PortControl::Configure(GCodeBuffer& gb, const StringRef& reply)
{
	bool seen = false;
	if (gb.Seen('C'))
	{
		seen = true;
		UpdatePorts(0);
		IoPort * portAddresses[MaxPorts];
		PinAccess access[MaxPorts];
		for (size_t i = 0; i < MaxPorts; ++i)
		{
			portAddresses[i] = &portMap[i];
			access[i] = PinAccess::write0;
		}
		numConfiguredPorts = IoPort::AssignPorts(gb, reply, PinUsedBy::gpio, MaxPorts, portAddresses, access);
		if (numConfiguredPorts == 0)
		{
			return true;
		}
	}
	if (gb.Seen('T'))
	{
		seen = true;
		advanceMillis = (unsigned int)constrain<int>(gb.GetIValue(), 0, 1000);
		advanceClocks = (advanceMillis * (uint64_t)StepTimer::StepClockRate)/1000;
	}
	if (!seen)
	{
		reply.printf("Advance %ums, ", advanceMillis);
		if (numConfiguredPorts == 0)
		{
			reply.cat("no port mapping configured");
		}
		else
		{
			reply.cat("ports");
			for (size_t i = 0; i < numConfiguredPorts; ++i)
			{
				reply.cat(' ');
				portMap[i].AppendPinName(reply);
			}
		}
	}
	return false;
}

void PortControl::UpdatePorts(IoBits_t newPortState)
{
	if (newPortState != currentPortState)
	{
		const IoBits_t bitsToClear = currentPortState & ~newPortState;
		const IoBits_t bitsToSet = newPortState & ~currentPortState;
		for (size_t i = 0; i < numConfiguredPorts; ++i)
		{
			const IoBits_t mask = 1u << i;
			if (bitsToClear & mask)
			{
				portMap[i].WriteDigital(false);
			}
			else if (bitsToSet & mask)
			{
				portMap[i].WriteDigital(true);
			}
		}
		currentPortState = newPortState;
	}
}

#endif

// End