Preliminary version for serving all files for Duet
Changed webserver and network code to support multiple concurrent connections Removed support for differential-mode ultrasonic z-sensor Reduced X and Y instantDv from 15 to 10 mm/sec to allow outlines of holes to e drawn at lower speed Changed temperature reading code to give thermistor disconnected reading of -273C when there is a negative high ADC offset correction
This commit is contained in:
parent
9149a1eb3a
commit
68e6ed2575
11 changed files with 1284 additions and 1383 deletions
|
@ -24,8 +24,8 @@ Licence: GPL
|
|||
#define CONFIGURATION_H
|
||||
|
||||
#define NAME "RepRapFirmware"
|
||||
#define VERSION "0.57y-dc42"
|
||||
#define DATE "2014-03-28"
|
||||
#define VERSION "0.57z-alpha-dc42"
|
||||
#define DATE "2014-04-06"
|
||||
#define LAST_AUTHOR "dc42"
|
||||
|
||||
// Other firmware that we might switch to be compatible with.
|
||||
|
|
439
Network.cpp
Normal file
439
Network.cpp
Normal file
|
@ -0,0 +1,439 @@
|
|||
/****************************************************************************************************
|
||||
|
||||
RepRapFirmware - Network: RepRapPro Ormerod with Arduino Due controller
|
||||
|
||||
Separated out from Platform.cpp by dc42, 2014-04-05
|
||||
|
||||
****************************************************************************************************/
|
||||
|
||||
#include "RepRapFirmware.h"
|
||||
#include "DueFlashStorage.h"
|
||||
|
||||
const uint8_t windowedSendPackets = 2;
|
||||
|
||||
|
||||
//***************************************************************************************************
|
||||
|
||||
// Network/Ethernet class
|
||||
|
||||
// C calls to interface with LWIP (http://savannah.nongnu.org/projects/lwip/)
|
||||
// These are implemented in, and called from, a modified version of httpd.c
|
||||
// in the network directory.
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// Transmit data to the Network
|
||||
|
||||
void RepRapNetworkSendOutput(char* data, int length, void* pcb, void* hs);
|
||||
|
||||
// Ask whether it is OK to send
|
||||
int RepRapNetworkCanSend(void* hs);
|
||||
|
||||
void RepRapNetworkConnectionError(void* h)
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->ConnectionError(h);
|
||||
}
|
||||
|
||||
// Called to put out a message via the RepRap firmware.
|
||||
|
||||
void RepRapNetworkMessage(const char* s)
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, s);
|
||||
}
|
||||
|
||||
// Called to push data into the RepRap firmware.
|
||||
|
||||
void RepRapNetworkReceiveInput(const char* data, int length, void* pcb, void* hs)
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->ReceiveInput(data, length, pcb, hs);
|
||||
}
|
||||
|
||||
// Called when transmission of outgoing data is complete to allow
|
||||
// the RepRap firmware to write more.
|
||||
|
||||
void RepRapNetworkSentPacketAcknowledged(void *hs)
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->SentPacketAcknowledged(hs);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Network::Network()
|
||||
{
|
||||
active = false;
|
||||
ethPinsInit();
|
||||
|
||||
//ResetEther();
|
||||
|
||||
// Construct the free list buffer
|
||||
|
||||
freeTransactions = NULL;
|
||||
readyTransactions = NULL;
|
||||
writingTransactions = NULL;
|
||||
closingTransactions = NULL;
|
||||
for (int8_t i = 0; i < HTTP_STATE_SIZE; i++)
|
||||
{
|
||||
freeTransactions = new NetRing(freeTransactions);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::AppendTransaction(NetRing** list, NetRing *r)
|
||||
{
|
||||
r->next = NULL;
|
||||
while (*list != NULL)
|
||||
{
|
||||
list = &((*list)->next);
|
||||
}
|
||||
*list = r;
|
||||
}
|
||||
|
||||
void Network::Init()
|
||||
{
|
||||
init_ethernet(reprap.GetPlatform()->IPAddress(), reprap.GetPlatform()->NetMask(), reprap.GetPlatform()->GateWay());
|
||||
active = true;
|
||||
}
|
||||
|
||||
void Network::Spin()
|
||||
{
|
||||
// debugPrintf("NetSpinEnter\n");
|
||||
if (active)
|
||||
{
|
||||
ethernet_task(); // keep the Ethernet running
|
||||
|
||||
// See if we can send anything
|
||||
NetRing* r = writingTransactions;
|
||||
if (r != NULL)
|
||||
{
|
||||
bool doClose = r->TrySendData(); // we must leave r on the list for now because of possible callback to release the input buffer
|
||||
writingTransactions = r->next;
|
||||
if (doClose)
|
||||
{
|
||||
r->closeRequestedTime = reprap.GetPlatform()->Time();
|
||||
AppendTransaction(&closingTransactions, r);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendTransaction(&writingTransactions, r);
|
||||
}
|
||||
}
|
||||
|
||||
// See if we can close any connections
|
||||
r = closingTransactions;
|
||||
if (r != NULL)
|
||||
{
|
||||
if (reprap.GetPlatform()->Time() - r->closeRequestedTime >= CLIENT_CLOSE_DELAY)
|
||||
{
|
||||
r->Close();
|
||||
closingTransactions = r->next;
|
||||
AppendTransaction(&freeTransactions, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
// debugPrintf("NetSpinExit\n");
|
||||
}
|
||||
|
||||
bool Network::HaveData() const
|
||||
{
|
||||
return active && readyTransactions != NULL;
|
||||
}
|
||||
|
||||
bool Network::Read(char& b)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
return readyTransactions->Read(b);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Network::Write(char b)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
readyTransactions->Write(b);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::Write(const char* s)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
readyTransactions->Write(s);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::SentPacketAcknowledged(void *hs)
|
||||
{
|
||||
NetRing *r = writingTransactions;
|
||||
while (r != NULL && r->hs != hs)
|
||||
{
|
||||
r = r->next;
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
r->SentPacketAcknowledged();
|
||||
return;
|
||||
}
|
||||
|
||||
r = closingTransactions;
|
||||
while (r != NULL && r->hs != hs)
|
||||
{
|
||||
r = r->next;
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
r->SentPacketAcknowledged();
|
||||
return;
|
||||
}
|
||||
debugPrintf("Network SentPacketAcknowledged: didn't find hs=%08x\n", (unsigned int)hs);
|
||||
}
|
||||
|
||||
void Network::ConnectionError(void* hs)
|
||||
{
|
||||
// h points to an http state block that the caller is about to release, so we need to stop referring to it.
|
||||
debugPrintf("Network: ConnectionError\n");
|
||||
|
||||
// See if it's a ready transaction
|
||||
NetRing* r = readyTransactions;
|
||||
while (r != NULL && r->hs == hs)
|
||||
{
|
||||
r = r->next;
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
r->SetConnectionLost();
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we were sending it
|
||||
r = writingTransactions;
|
||||
while (r != NULL && r->hs == hs)
|
||||
{
|
||||
r = r->next;
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
r->SetConnectionLost();
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we were closing it
|
||||
r = closingTransactions;
|
||||
while (r != NULL && r->hs == hs)
|
||||
{
|
||||
r = r->next;
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
r->SetConnectionLost();
|
||||
return;
|
||||
}
|
||||
|
||||
// Else we didn't identify the transaction - maybe we already asked to close it
|
||||
debugPrintf("Network ConnectionError: didn't find hs=%08x\n", (unsigned int)hs);
|
||||
}
|
||||
|
||||
void Network::ReceiveInput(const char* data, int length, void* pcb, void* hs)
|
||||
{
|
||||
NetRing* r = freeTransactions;
|
||||
if (r == NULL)
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::ReceiveInput() - no free transactions!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
freeTransactions = r->next;
|
||||
|
||||
r->Set(data, length, pcb, hs);
|
||||
AppendTransaction(&readyTransactions, r);
|
||||
// debugPrintf("Network - input received\n");
|
||||
}
|
||||
|
||||
// Send the output data we already have, optionally with a file appended, then close the connection.
|
||||
// The file may be too large for our buffer, so we may have to send it in multiple transactions.
|
||||
void Network::SendAndClose(FileStore *f)
|
||||
{
|
||||
NetRing *r = readyTransactions;
|
||||
if (r != NULL)
|
||||
{
|
||||
readyTransactions = r->next;
|
||||
if (r->LostConnection())
|
||||
{
|
||||
if (f != NULL)
|
||||
{
|
||||
f->Close();
|
||||
}
|
||||
AppendTransaction(&freeTransactions, r);
|
||||
debugPrintf("Conn lost before send\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
r->fileBeingSent = f;
|
||||
AppendTransaction(&writingTransactions, r);
|
||||
//debug
|
||||
// r->outputBuffer[r->outputPointer] = 0;
|
||||
// debugPrintf("Transaction queued for writing to network, file=%c, data=%s\n", (f ? 'Y' : 'N'), r->outputBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//queries the PHY for link status, true = link is up, false, link is down or there is some other error
|
||||
bool Network::LinkIsUp()
|
||||
{
|
||||
return status_link_up();
|
||||
}
|
||||
|
||||
bool Network::Active() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
// NetRing class members
|
||||
NetRing::NetRing(NetRing* n) : next(n)
|
||||
{
|
||||
}
|
||||
|
||||
void NetRing::Set(const char* d, int l, void* pc, void* h)
|
||||
{
|
||||
pcb = pc;
|
||||
hs = h;
|
||||
inputData = d;
|
||||
inputLength = l;
|
||||
inputPointer = 0;
|
||||
outputPointer = 0;
|
||||
sentPacketsOutstanding = 0;
|
||||
fileBeingSent = NULL;
|
||||
}
|
||||
|
||||
// Webserver calls this to read bytes that have come in from the network
|
||||
|
||||
bool NetRing::Read(char& b)
|
||||
{
|
||||
if (LostConnection() || inputPointer >= inputLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
b = inputData[inputPointer];
|
||||
inputPointer++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Webserver calls this to write bytes that need to go out to the network
|
||||
|
||||
void NetRing::Write(char b)
|
||||
{
|
||||
if (LostConnection()) return;
|
||||
|
||||
if (outputPointer >= ARRAY_SIZE(outputBuffer))
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::Write(char b) - Output buffer overflow! \n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the byte to the buffer
|
||||
|
||||
outputBuffer[outputPointer] = b;
|
||||
outputPointer++;
|
||||
}
|
||||
|
||||
// This is not called for data, only for internally-
|
||||
// generated short strings at the start of a transmission,
|
||||
// so it should never overflow the buffer (which is checked
|
||||
// anyway).
|
||||
|
||||
void NetRing::Write(const char* s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
Write(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
// Send some data if we can, returning true if all data has been sent
|
||||
bool NetRing::TrySendData()
|
||||
{
|
||||
if (LostConnection())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!RepRapNetworkCanSend(hs))
|
||||
{
|
||||
// debugPrintf("Send busy\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sentPacketsOutstanding >= windowedSendPackets)
|
||||
{
|
||||
// debugPrintf("Awaiting ack\n");
|
||||
return false; // still waiting for earlier packets to be acknowledged
|
||||
}
|
||||
|
||||
if (fileBeingSent != NULL)
|
||||
{
|
||||
while (outputPointer < ARRAY_SIZE(outputBuffer))
|
||||
{
|
||||
bool ok = fileBeingSent->Read(outputBuffer[outputPointer]);
|
||||
if (!ok)
|
||||
{
|
||||
fileBeingSent->Close();
|
||||
fileBeingSent = NULL;
|
||||
break;
|
||||
}
|
||||
++outputPointer;
|
||||
}
|
||||
// debugPrintf("Read from file\n");
|
||||
}
|
||||
|
||||
if (outputPointer == 0)
|
||||
{
|
||||
// debugPrintf("All data sent\n");
|
||||
return true;
|
||||
// return sentPacketsOutstanding == 0; // no more data to send, so tell caller to close file if all packets acknowledged
|
||||
}
|
||||
else
|
||||
{
|
||||
// debugPrintf("Sending data, hs=%08x, length=%d\n", (unsigned int)hs, outputPointer);
|
||||
++sentPacketsOutstanding;
|
||||
RepRapNetworkSendOutput(outputBuffer, outputPointer, pcb, hs);
|
||||
outputPointer = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void NetRing::SentPacketAcknowledged()
|
||||
{
|
||||
if (sentPacketsOutstanding != 0)
|
||||
{
|
||||
--sentPacketsOutstanding;
|
||||
}
|
||||
}
|
||||
|
||||
// Close this connection. Return true if it really is closed, false if it needs to go in the deferred close list.
|
||||
bool NetRing::Close()
|
||||
{
|
||||
if (LostConnection())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// debugPrintf("Closing connection hs=%08x\n", (unsigned int)hs);
|
||||
RepRapNetworkSendOutput((char*) NULL, 0, pcb, hs);
|
||||
return true; // try not using deferred close for now
|
||||
}
|
||||
|
||||
void NetRing::SetConnectionLost()
|
||||
{
|
||||
hs = NULL;
|
||||
}
|
||||
|
||||
bool NetRing::LostConnection() const
|
||||
{
|
||||
return hs == NULL;
|
||||
}
|
||||
|
||||
|
||||
// End
|
104
Network.h
Normal file
104
Network.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/****************************************************************************************************
|
||||
|
||||
RepRapFirmware - Network: RepRapPro Ormerod with Duet controller
|
||||
|
||||
Separated out from Platform.h by dc42
|
||||
|
||||
****************************************************************************************************/
|
||||
|
||||
#ifndef NETWORK_H
|
||||
#define NETWORK_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Platform-specific includes
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "ethernet_sam.h"
|
||||
|
||||
// This class handles the network - typically an Ethernet.
|
||||
|
||||
// The size of the http output buffer is critical to getting fast load times in the browser.
|
||||
// If this value is less than the TCP MSS, then Chrome under Windows will delay ack messages by about 120ms,
|
||||
// which results in very slow page loading. Any value higher than that will cause the TCP packet to be split
|
||||
// into multiple transmissions, which avoids this behaviour. Using a value of twice the MSS is most efficient because
|
||||
// each TCP packet will be full.
|
||||
// Currently we set the MSS (in file network/lwipopts.h) to 1432 which matches the value used by most versions of Windows
|
||||
// and therefore avoids additional memory use and fragmentation.
|
||||
const unsigned int httpOutputBufferSize = 2 * 1432;
|
||||
|
||||
// Start with a ring buffer to hold input from the network that needs to be responded to.
|
||||
|
||||
class NetRing
|
||||
{
|
||||
public:
|
||||
friend class Network;
|
||||
|
||||
protected:
|
||||
NetRing(NetRing* n);
|
||||
void Set(const char* d, int l, void* pc, void* h);
|
||||
bool Read(char& b);
|
||||
void SentPacketAcknowledged();
|
||||
void Write(char b);
|
||||
void Write(const char* s);
|
||||
bool Close();
|
||||
bool TrySendData();
|
||||
void SetConnectionLost();
|
||||
bool LostConnection() const;
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void* pcb;
|
||||
void* hs;
|
||||
|
||||
NetRing* next;
|
||||
const char* inputData;
|
||||
int inputLength;
|
||||
int inputPointer;
|
||||
uint8_t sentPacketsOutstanding; // count of TCP packets we have sent that have not been acknowledged
|
||||
char outputBuffer[httpOutputBufferSize];
|
||||
int outputPointer;
|
||||
bool closePending;
|
||||
FileStore *fileBeingSent;
|
||||
float closeRequestedTime;
|
||||
};
|
||||
|
||||
// The main network class that drives the network.
|
||||
|
||||
class Network
|
||||
{
|
||||
public:
|
||||
|
||||
void ReceiveInput(const char* data, int length, void* pc, void* h);
|
||||
void InputBufferReleased(void *hs, void* pb);
|
||||
void SentPacketAcknowledged(void *hs);
|
||||
void ConnectionError(void* h);
|
||||
bool Active() const;
|
||||
bool LinkIsUp();
|
||||
bool Read(char& b);
|
||||
void Write(char b);
|
||||
void Write(const char* s);
|
||||
void SendAndClose(FileStore *f);
|
||||
bool HaveData() const;
|
||||
|
||||
Network();
|
||||
void Init();
|
||||
void Spin();
|
||||
|
||||
private:
|
||||
|
||||
void AppendTransaction(NetRing** list, NetRing *r);
|
||||
|
||||
NetRing *freeTransactions;
|
||||
NetRing *readyTransactions;
|
||||
NetRing *writingTransactions;
|
||||
NetRing *closingTransactions;
|
||||
bool active;
|
||||
};
|
||||
|
||||
#endif
|
490
Platform.cpp
490
Platform.cpp
|
@ -286,7 +286,6 @@ void Platform::InitZProbe()
|
|||
{
|
||||
zProbeOnFilter.Init();
|
||||
zProbeOffFilter.Init();
|
||||
ResetZProbeMinSum();
|
||||
|
||||
if (nvData.zProbeType == 1 || nvData.zProbeType == 2)
|
||||
{
|
||||
|
@ -294,7 +293,7 @@ void Platform::InitZProbe()
|
|||
digitalWrite(zProbeModulationPin, HIGH); // enable the IR LED
|
||||
SetZProbing(false);
|
||||
}
|
||||
else if (nvData.zProbeType == 3 || nvData.zProbeType == 4)
|
||||
else if (nvData.zProbeType == 3)
|
||||
{
|
||||
pinMode(zProbeModulationPin, OUTPUT);
|
||||
digitalWrite(zProbeModulationPin, LOW); // enable the ultrasonic sensor
|
||||
|
@ -323,20 +322,7 @@ int Platform::ZProbe()
|
|||
case 2:
|
||||
// Modulated IR sensor. We assume that zProbeOnFilter and zprobeOffFilter average the same number of readings.
|
||||
// Because of noise, it is possible to get a negative reading, so allow for this.
|
||||
return (int) (((int32_t) zProbeOnFilter.GetSum() - (int32_t) zProbeOffFilter.GetSum())
|
||||
/ (4 * numZProbeReadingsAveraged));
|
||||
|
||||
case 4:
|
||||
// Ultrasonic sensor in differential mode. We assume that zProbeOnFilter and zprobeOffFilter average the same number of readings.
|
||||
{
|
||||
uint32_t sum = zProbeOnFilter.GetSum() + zProbeOffFilter.GetSum();
|
||||
if (sum < zProbeMinSum)
|
||||
{
|
||||
zProbeMinSum = sum;
|
||||
}
|
||||
uint32_t total = zProbeOnFilter.GetSum() + zProbeOffFilter.GetSum();
|
||||
return (int) ((total - zProbeMinSum) / (4 * numZProbeReadingsAveraged));
|
||||
}
|
||||
return (int) (((int32_t) zProbeOnFilter.GetSum() - (int32_t) zProbeOffFilter.GetSum()) / (4 * numZProbeReadingsAveraged));
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -355,17 +341,6 @@ int Platform::GetZProbeSecondaryValues(int& v1, int& v2)
|
|||
case 2: // modulated IR sensor
|
||||
v1 = (int) (zProbeOnFilter.GetSum() / (4 * numZProbeReadingsAveraged)); // pass back the reading with IR turned on
|
||||
return 1;
|
||||
case 4: // differential ultrasonic
|
||||
{
|
||||
uint32_t sum = zProbeOnFilter.GetSum() + zProbeOffFilter.GetSum();
|
||||
if (sum < zProbeMinSum)
|
||||
{
|
||||
zProbeMinSum = sum;
|
||||
}
|
||||
v1 = (int) ((zProbeOnFilter.GetSum() + zProbeOffFilter.GetSum()) / (8 * numZProbeReadingsAveraged)); // pass back the raw reading
|
||||
v2 = (int) (zProbeMinSum / (8 * numZProbeReadingsAveraged)); // pass back the minimum found
|
||||
}
|
||||
return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -386,7 +361,6 @@ float Platform::ZProbeStopHeight() const
|
|||
case 2:
|
||||
return nvData.irZProbeParameters.GetStopHeight(GetTemperature(0));
|
||||
case 3:
|
||||
case 4:
|
||||
return nvData.ultrasonicZProbeParameters.GetStopHeight(GetTemperature(0));
|
||||
default:
|
||||
return 0;
|
||||
|
@ -395,7 +369,7 @@ float Platform::ZProbeStopHeight() const
|
|||
|
||||
void Platform::SetZProbeType(int pt)
|
||||
{
|
||||
int newZProbeType = (pt >= 0 && pt <= 4) ? pt : 0;
|
||||
int newZProbeType = (pt >= 0 && pt <= 3) ? pt : 0;
|
||||
if (newZProbeType != nvData.zProbeType)
|
||||
{
|
||||
nvData.zProbeType = newZProbeType;
|
||||
|
@ -413,7 +387,6 @@ bool Platform::GetZProbeParameters(struct ZProbeParameters& params) const
|
|||
params = nvData.irZProbeParameters;
|
||||
return true;
|
||||
case 3:
|
||||
case 4:
|
||||
params = nvData.ultrasonicZProbeParameters;
|
||||
return true;
|
||||
default:
|
||||
|
@ -434,7 +407,6 @@ bool Platform::SetZProbeParameters(const struct ZProbeParameters& params)
|
|||
}
|
||||
return true;
|
||||
case 3:
|
||||
case 4:
|
||||
if (nvData.ultrasonicZProbeParameters != params)
|
||||
{
|
||||
nvData.ultrasonicZProbeParameters = params;
|
||||
|
@ -459,15 +431,6 @@ void Platform::WriteNvData()
|
|||
|
||||
void Platform::SetZProbing(bool starting)
|
||||
{
|
||||
if (starting && nvData.zProbeType == 4)
|
||||
{
|
||||
ResetZProbeMinSum(); // look for a new minimum
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::ResetZProbeMinSum()
|
||||
{
|
||||
zProbeMinSum = adRangeReal * numZProbeReadingsAveraged * 2;
|
||||
}
|
||||
|
||||
// Note: the use of floating point time will cause the resolution to degrade over time.
|
||||
|
@ -607,8 +570,7 @@ void Platform::DisableInterrupts()
|
|||
// 0. Kick the watchdog.
|
||||
// 1. Kick off a new ADC conversion.
|
||||
// 2. Fetch and process the result of the last ADC conversion.
|
||||
// 3a. If the last ADC conversion was for the Z probe, toggle the modulation output if using a modulated IR sensor,
|
||||
// or update the minimum reading if using an ultrasonic sensor in differential mode.
|
||||
// 3a. If the last ADC conversion was for the Z probe, toggle the modulation output if using a modulated IR sensor.
|
||||
// 3b. If the last ADC reading was a thermistor reading, check for an over-temperature situation and turn off the heater if necessary.
|
||||
// We do this here because the usual polling loop sometimes gets stuck trying to send data to the USB port.
|
||||
|
||||
|
@ -619,21 +581,19 @@ void Platform::Tick()
|
|||
#ifdef TIME_TICK_ISR
|
||||
uint32_t now = micros();
|
||||
#endif
|
||||
WDT_Restart(WDT);
|
||||
WDT_Restart(WDT); // kick the watchdog
|
||||
switch (tickState)
|
||||
{
|
||||
case 1: // last conversion started was a thermistor
|
||||
case 3:
|
||||
{
|
||||
ThermistorAveragingFilter& currentFilter =
|
||||
const_cast<ThermistorAveragingFilter&>(thermistorFilters[currentHeater]);
|
||||
ThermistorAveragingFilter& currentFilter = const_cast<ThermistorAveragingFilter&>(thermistorFilters[currentHeater]);
|
||||
currentFilter.ProcessReading(GetAdcReading(heaterAdcChannels[currentHeater]));
|
||||
StartAdcConversion(zProbeAdcChannel);
|
||||
if (currentFilter.IsValid())
|
||||
{
|
||||
uint32_t sum = currentFilter.GetSum();
|
||||
if (sum < thermistorOverheatSums[currentHeater]
|
||||
|| sum >= adDisconnectedReal * numThermistorReadingsAveraged)
|
||||
if (sum < thermistorOverheatSums[currentHeater] || sum >= adDisconnectedReal * numThermistorReadingsAveraged)
|
||||
{
|
||||
// We have an over-temperature or bad reading from this thermistor, so turn off the heater
|
||||
// NB - the SetHeater function we call does floating point maths, but this is an exceptional situation so we allow it
|
||||
|
@ -692,7 +652,7 @@ void Platform::Tick()
|
|||
/*static*/void Platform::StartAdcConversion(adc_channel_num_t chan)
|
||||
{
|
||||
adc_enable_channel(ADC, chan);
|
||||
adc_start(ADC );
|
||||
adc_start(ADC);
|
||||
}
|
||||
|
||||
// Convert an Arduino Due pin number to the corresponding ADC channel number
|
||||
|
@ -815,16 +775,25 @@ void Platform::ClassReport(char* className, float &lastTime)
|
|||
|
||||
float Platform::GetTemperature(size_t heater) const
|
||||
{
|
||||
// If the ADC reading is N then for an ideal ADC, the input voltage is at least N/(AD_RANGE + 1) and less than (N + 1)/(AD_RANGE + 1), times the analog reference.
|
||||
// So we add 0.5 to to the reading to get a better estimate of the input. But first, recognise the special case of thermistor disconnected.
|
||||
int rawTemp = GetRawTemperature(heater);
|
||||
|
||||
// If the ADC reading is N then for an ideal ADC, the input voltage is at least N/(AD_RANGE + 1) and less than (N + 1)/(AD_RANGE + 1), times the analog reference.
|
||||
// So we add 0.5 to to the reading to get a better estimate of the input.
|
||||
|
||||
float reading = (float) rawTemp + 0.5;
|
||||
|
||||
// Recognise the special case of thermistor disconnected.
|
||||
// For some ADCs, the high-end offset is negative, meaning that the ADC never returns a high enough value. We need to allow for this here.
|
||||
|
||||
const PidParameters& p = nvData.pidParams[heater];
|
||||
if (p.adcHighOffset < 0)
|
||||
{
|
||||
rawTemp -= (int)p.adcHighOffset;
|
||||
}
|
||||
if (rawTemp >= adDisconnectedVirtual)
|
||||
{
|
||||
// Thermistor is disconnected
|
||||
return ABS_ZERO;
|
||||
return ABS_ZERO; // thermistor is disconnected
|
||||
}
|
||||
float reading = (float) rawTemp + 0.5;
|
||||
const PidParameters& p = nvData.pidParams[heater];
|
||||
|
||||
// Correct for the low and high ADC offsets
|
||||
reading -= p.adcLowOffset;
|
||||
|
@ -872,8 +841,8 @@ EndStopHit Platform::Stopped(int8_t drive)
|
|||
{
|
||||
int zProbeVal = ZProbe();
|
||||
int zProbeADValue =
|
||||
(nvData.zProbeType == 3 || nvData.zProbeType == 4) ?
|
||||
nvData.ultrasonicZProbeParameters.adcValue : nvData.irZProbeParameters.adcValue;
|
||||
(nvData.zProbeType == 3) ? nvData.ultrasonicZProbeParameters.adcValue
|
||||
: nvData.irZProbeParameters.adcValue;
|
||||
if (zProbeVal >= zProbeADValue)
|
||||
return lowHit;
|
||||
else if (zProbeVal * 10 >= zProbeADValue * 9) // if we are at/above 90% of the target value
|
||||
|
@ -1390,411 +1359,4 @@ void Line::Spin()
|
|||
}
|
||||
}
|
||||
|
||||
//***************************************************************************************************
|
||||
|
||||
// Network/Ethernet class
|
||||
|
||||
// C calls to interface with LWIP (http://savannah.nongnu.org/projects/lwip/)
|
||||
// These are implemented in, and called from, a modified version of httpd.c
|
||||
// in the network directory.
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
//void ResetEther();
|
||||
|
||||
// Transmit data to the Network
|
||||
|
||||
void RepRapNetworkSendOutput(char* data, int length, void* pbuf, void* pcb, void* hs);
|
||||
|
||||
// When lwip releases storage, set the local copy of the pointer to 0 to stop
|
||||
// it being used again.
|
||||
|
||||
void RepRapNetworkInputBufferReleased(void* pb)
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->InputBufferReleased(pb);
|
||||
}
|
||||
|
||||
void RepRapNetworkConnectionError(void* h)
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->ConnectionError(h);
|
||||
reprap.GetWebserver()->ConnectionError();
|
||||
}
|
||||
|
||||
// Called to put out a message via the RepRap firmware.
|
||||
|
||||
void RepRapNetworkMessage(char* s)
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, s);
|
||||
}
|
||||
|
||||
// Called to push data into the RepRap firmware.
|
||||
|
||||
void RepRapNetworkReceiveInput(char* data, int length, void* pbuf, void* pcb, void* hs)
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->ReceiveInput(data, length, pbuf, pcb, hs);
|
||||
}
|
||||
|
||||
// Called when transmission of outgoing data is complete to allow
|
||||
// the RepRap firmware to write more.
|
||||
|
||||
void RepRapNetworkSentPacketAcknowledged()
|
||||
{
|
||||
reprap.GetPlatform()->GetNetwork()->SentPacketAcknowledged();
|
||||
}
|
||||
|
||||
bool RepRapNetworkHasALiveClient()
|
||||
{
|
||||
return reprap.GetPlatform()->GetNetwork()->Status() & clientLive;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Network::Network()
|
||||
{
|
||||
active = false;
|
||||
ethPinsInit();
|
||||
|
||||
//ResetEther();
|
||||
|
||||
// Construct the ring buffer
|
||||
|
||||
netRingAddPointer = new NetRing(NULL);
|
||||
netRingGetPointer = netRingAddPointer;
|
||||
for (int8_t i = 1; i < HTTP_STATE_SIZE; i++)
|
||||
netRingGetPointer = new NetRing(netRingGetPointer);
|
||||
netRingAddPointer->SetNext(netRingGetPointer);
|
||||
}
|
||||
|
||||
// Reset the network to its disconnected and ready state.
|
||||
|
||||
void Network::Reset()
|
||||
{
|
||||
//reprap.GetPlatform()->Message(HOST_MESSAGE, "Reset.\n");
|
||||
inputPointer = 0;
|
||||
inputLength = -1;
|
||||
outputPointer = 0;
|
||||
writeEnabled = false;
|
||||
closePending = false;
|
||||
status = nothing;
|
||||
sentPacketsOutstanding = 0;
|
||||
}
|
||||
|
||||
void Network::CleanRing()
|
||||
{
|
||||
for (int8_t i = 0; i <= HTTP_STATE_SIZE; i++)
|
||||
{
|
||||
netRingGetPointer->Free();
|
||||
netRingGetPointer = netRingGetPointer->Next();
|
||||
}
|
||||
netRingAddPointer = netRingGetPointer;
|
||||
}
|
||||
|
||||
void Network::Init()
|
||||
{
|
||||
CleanRing();
|
||||
Reset();
|
||||
|
||||
init_ethernet(reprap.GetPlatform()->IPAddress(), reprap.GetPlatform()->NetMask(), reprap.GetPlatform()->GateWay());
|
||||
active = true;
|
||||
sentPacketsOutstanding = 0;
|
||||
}
|
||||
|
||||
void Network::Spin()
|
||||
{
|
||||
if (!active)
|
||||
{
|
||||
//ResetEther();
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep the Ethernet running
|
||||
|
||||
ethernet_task();
|
||||
|
||||
// Anything come in from the network to act on?
|
||||
|
||||
if (!netRingGetPointer->Active())
|
||||
return;
|
||||
|
||||
// Finished reading the active ring element?
|
||||
|
||||
if (!netRingGetPointer->ReadFinished())
|
||||
{
|
||||
// No - Finish reading any data that's been received.
|
||||
|
||||
if (inputPointer < inputLength)
|
||||
return;
|
||||
|
||||
// Haven't started reading it yet - set that up.
|
||||
|
||||
inputPointer = 0;
|
||||
inputLength = netRingGetPointer->Length();
|
||||
inputBuffer = netRingGetPointer->Data();
|
||||
}
|
||||
}
|
||||
|
||||
// Webserver calls this to read bytes that have come in from the network
|
||||
|
||||
bool Network::Read(char& b)
|
||||
{
|
||||
if (inputPointer >= inputLength)
|
||||
{
|
||||
inputLength = -1;
|
||||
inputPointer = 0;
|
||||
netRingGetPointer->SetReadFinished(); // Past tense...
|
||||
SetWriteEnable(true);
|
||||
//reprap.GetPlatform()->Message(HOST_MESSAGE, "Network - data read.\n");
|
||||
return false;
|
||||
}
|
||||
b = inputBuffer[inputPointer];
|
||||
inputPointer++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Webserver calls this to write bytes that need to go out to the network
|
||||
|
||||
void Network::Write(char b)
|
||||
{
|
||||
// Check for horrible things...
|
||||
|
||||
if (!CanWrite())
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::Write(char b) - Attempt to write when disabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputPointer >= ARRAY_SIZE(outputBuffer))
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::Write(char b) - Output buffer overflow! \n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the byte to the buffer
|
||||
|
||||
outputBuffer[outputPointer] = b;
|
||||
outputPointer++;
|
||||
|
||||
// Buffer full? If so, send it.
|
||||
|
||||
if (outputPointer == ARRAY_SIZE(outputBuffer))
|
||||
{
|
||||
#if WINDOWED_SEND_PACKETS > 1
|
||||
++sentPacketsOutstanding;
|
||||
#else
|
||||
SetWriteEnable(false); // Stop further writing from Webserver until the network tells us that this has gone
|
||||
#endif
|
||||
RepRapNetworkSendOutput(outputBuffer, outputPointer, netRingGetPointer->Pbuf(), netRingGetPointer->Pcb(),
|
||||
netRingGetPointer->Hs());
|
||||
outputPointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Network::InputBufferReleased(void* pb)
|
||||
{
|
||||
if (netRingGetPointer->Pbuf() != pb)
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::InputBufferReleased() - Pointers don't match!\n");
|
||||
return;
|
||||
}
|
||||
netRingGetPointer->ReleasePbuf();
|
||||
}
|
||||
|
||||
void Network::ConnectionError(void* h)
|
||||
{
|
||||
// h points to an http state block that the caller is about to release, so we need to stop referring to it.
|
||||
// The state block is usually but not always in use by the current http request being processed, in which case we abandon the current request.
|
||||
if (netRingGetPointer != netRingAddPointer && netRingGetPointer->Hs() == h)
|
||||
{
|
||||
netRingGetPointer->Free();
|
||||
netRingGetPointer = netRingGetPointer->Next();
|
||||
}
|
||||
|
||||
// Reset the network layer. In particular, this clears the output buffer to make sure nothing more gets sent,
|
||||
// and sets status to 'nothing' so that we can accept another connection attempt.
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Network::ReceiveInput(char* data, int length, void* pbuf, void* pcb, void* hs)
|
||||
{
|
||||
status = clientLive;
|
||||
if (netRingAddPointer->Active())
|
||||
{
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::ReceiveInput() - Ring buffer full!\n");
|
||||
return;
|
||||
}
|
||||
netRingAddPointer->Set(data, length, pbuf, pcb, hs);
|
||||
netRingAddPointer = netRingAddPointer->Next();
|
||||
//reprap.GetPlatform()->Message(HOST_MESSAGE, "Network - input received.\n");
|
||||
}
|
||||
|
||||
bool Network::CanWrite() const
|
||||
{
|
||||
#if WINDOWED_SEND_PACKETS > 1
|
||||
return writeEnabled && sentPacketsOutstanding < WINDOWED_SEND_PACKETS;
|
||||
#else
|
||||
return writeEnabled;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Network::SetWriteEnable(bool enable)
|
||||
{
|
||||
writeEnabled = enable;
|
||||
if (!writeEnabled)
|
||||
return;
|
||||
if (closePending)
|
||||
Close();
|
||||
}
|
||||
|
||||
void Network::SentPacketAcknowledged()
|
||||
{
|
||||
#if WINDOWED_SEND_PACKETS > 1
|
||||
if (sentPacketsOutstanding != 0)
|
||||
{
|
||||
--sentPacketsOutstanding;
|
||||
}
|
||||
if (closePending && sentPacketsOutstanding == 0)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
#else
|
||||
SetWriteEnable(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is not called for data, only for internally-
|
||||
// generated short strings at the start of a transmission,
|
||||
// so it should never overflow the buffer (which is checked
|
||||
// anyway).
|
||||
|
||||
void Network::Write(const char* s)
|
||||
{
|
||||
int i = 0;
|
||||
while (s[i])
|
||||
Write(s[i++]);
|
||||
}
|
||||
|
||||
void Network::Close()
|
||||
{
|
||||
if (Status() && clientLive)
|
||||
{
|
||||
if (outputPointer > 0)
|
||||
{
|
||||
SetWriteEnable(false);
|
||||
RepRapNetworkSendOutput(outputBuffer, outputPointer, netRingGetPointer->Pbuf(), netRingGetPointer->Pcb(),
|
||||
netRingGetPointer->Hs());
|
||||
outputPointer = 0;
|
||||
closePending = true;
|
||||
return;
|
||||
}
|
||||
RepRapNetworkSendOutput((char*) NULL, 0, netRingGetPointer->Pbuf(), netRingGetPointer->Pcb(),
|
||||
netRingGetPointer->Hs());
|
||||
netRingGetPointer->Free();
|
||||
netRingGetPointer = netRingGetPointer->Next();
|
||||
//reprap.GetPlatform()->Message(HOST_MESSAGE, "Network - output sent and closed.\n");
|
||||
}
|
||||
else
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::Close() - Attempt to close a closed connection!\n");
|
||||
closePending = false;
|
||||
status = nothing;
|
||||
//Reset();
|
||||
}
|
||||
|
||||
int8_t Network::Status() const
|
||||
{
|
||||
if (inputPointer >= inputLength)
|
||||
return status;
|
||||
return status | clientConnected | byteAvailable;
|
||||
}
|
||||
|
||||
NetRing::NetRing(NetRing* n)
|
||||
{
|
||||
next = n;
|
||||
Free();
|
||||
}
|
||||
|
||||
void NetRing::Free()
|
||||
{
|
||||
pbuf = 0;
|
||||
pcb = 0;
|
||||
hs = 0;
|
||||
data = "";
|
||||
length = 0;
|
||||
read = false;
|
||||
active = false;
|
||||
}
|
||||
|
||||
bool NetRing::Set(char* d, int l, void* pb, void* pc, void* h)
|
||||
{
|
||||
if (active)
|
||||
return false;
|
||||
pbuf = pb;
|
||||
pcb = pc;
|
||||
hs = h;
|
||||
data = d;
|
||||
length = l;
|
||||
read = false;
|
||||
active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
NetRing* NetRing::Next()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
char* NetRing::Data()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
int NetRing::Length()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
bool NetRing::ReadFinished()
|
||||
{
|
||||
return read;
|
||||
}
|
||||
|
||||
void NetRing::SetReadFinished()
|
||||
{
|
||||
read = true;
|
||||
}
|
||||
|
||||
bool NetRing::Active()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
void NetRing::SetNext(NetRing* n)
|
||||
{
|
||||
next = n;
|
||||
}
|
||||
|
||||
void* NetRing::Pbuf()
|
||||
{
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
void NetRing::ReleasePbuf()
|
||||
{
|
||||
pbuf = 0;
|
||||
}
|
||||
|
||||
void* NetRing::Pcb()
|
||||
{
|
||||
return pcb;
|
||||
}
|
||||
|
||||
void* NetRing::Hs()
|
||||
{
|
||||
return hs;
|
||||
}
|
||||
|
||||
void NetRing::ReleaseHs()
|
||||
{
|
||||
hs = 0;
|
||||
}
|
||||
|
||||
// End
|
||||
|
|
124
Platform.h
124
Platform.h
|
@ -101,7 +101,7 @@ const unsigned int numZProbeReadingsAveraged = 8; // we average this number of r
|
|||
#define MAX_FEEDRATES {50.0, 50.0, 3.0, 16.0} // mm/sec
|
||||
#define ACCELERATIONS {800.0, 800.0, 10.0, 250.0} // mm/sec^2
|
||||
#define DRIVE_STEPS_PER_UNIT {87.4890, 87.4890, 4000.0, 420.0}
|
||||
#define INSTANT_DVS {15.0, 15.0, 0.2, 2.0} // (mm/sec)
|
||||
#define INSTANT_DVS {10.0, 10.0, 0.2, 2.0} // (mm/sec)
|
||||
|
||||
// AXES
|
||||
|
||||
|
@ -212,21 +212,12 @@ const unsigned int adDisconnectedVirtual = adDisconnectedReal << adOversampleBit
|
|||
|
||||
#define CLIENT_CLOSE_DELAY 0.002
|
||||
|
||||
#define HTTP_STATE_SIZE 5
|
||||
#define HTTP_STATE_SIZE 7
|
||||
|
||||
#define IP_ADDRESS {192, 168, 1, 10} // Need some sort of default...
|
||||
#define NET_MASK {255, 255, 255, 0}
|
||||
#define GATE_WAY {192, 168, 1, 1}
|
||||
|
||||
// The size of the http output buffer is critical to getting fast load times in the browser.
|
||||
// If this value is less than the TCP MSS, then Chrome under Windows will delay ack messages by about 120ms,
|
||||
// which results in very slow page loading. Any value higher than that will cause the TCP packet to be split
|
||||
// into multiple transmissions, which avoids this behaviour. Using a value of twice the MSS is most efficient because
|
||||
// each TCP packet will be full.
|
||||
// Currently we set the MSS (in file network/lwipopts.h) to 1432 which matches the value used by most versions of Windows
|
||||
// and therefore avoids additional memory use and fragmentation.
|
||||
const unsigned int httpOutputBufferSize = 2 * 1432;
|
||||
|
||||
|
||||
/****************************************************************************************************/
|
||||
|
||||
|
@ -263,103 +254,6 @@ enum IOStatus
|
|||
clientConnected = 8
|
||||
};
|
||||
|
||||
//// All IO is done by classes derived from this class.
|
||||
//
|
||||
//class InputOutput
|
||||
//{
|
||||
//public:
|
||||
// void TakeInputFrom(InputOutput* altIp);
|
||||
// void SendOutputTo(InputOutput* altOp);
|
||||
//
|
||||
//protected:
|
||||
// InputOutput* alternateInput;
|
||||
// InputOutput* alternateOutput;
|
||||
//};
|
||||
|
||||
// This class handles the network - typically an Ethernet.
|
||||
|
||||
// Start with a ring buffer to hold input from the network
|
||||
// that needs to be responded to.
|
||||
|
||||
class NetRing
|
||||
{
|
||||
public:
|
||||
friend class Network;
|
||||
|
||||
protected:
|
||||
NetRing(NetRing* n);
|
||||
NetRing* Next();
|
||||
bool Set(char* d, int l, void* pb, void* pc, void* h);
|
||||
char* Data();
|
||||
int Length();
|
||||
bool ReadFinished();
|
||||
void SetReadFinished();
|
||||
void* Pbuf();
|
||||
void* Pcb();
|
||||
void* Hs();
|
||||
bool Active();
|
||||
void Free();
|
||||
void SetNext(NetRing* n);
|
||||
void ReleasePbuf();
|
||||
void ReleaseHs();
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void* pbuf;
|
||||
void* pcb;
|
||||
void* hs;
|
||||
char* data;
|
||||
int length;
|
||||
bool read;
|
||||
bool active;
|
||||
NetRing* next;
|
||||
};
|
||||
|
||||
// The main network class that drives the network.
|
||||
|
||||
class Network //: public InputOutput
|
||||
{
|
||||
public:
|
||||
|
||||
int8_t Status() const; // Returns OR of IOStatus
|
||||
bool Read(char& b);
|
||||
bool CanWrite() const;
|
||||
void SetWriteEnable(bool enable);
|
||||
void SentPacketAcknowledged();
|
||||
void Write(char b);
|
||||
void Write(const char* s);
|
||||
void Close();
|
||||
void ReceiveInput(char* data, int length, void* pb, void* pc, void* h);
|
||||
void InputBufferReleased(void* pb);
|
||||
void ConnectionError(void* h);
|
||||
bool Active() const;
|
||||
bool LinkIsUp();
|
||||
|
||||
friend class Platform;
|
||||
|
||||
protected:
|
||||
|
||||
Network();
|
||||
void Init();
|
||||
void Spin();
|
||||
|
||||
private:
|
||||
|
||||
void Reset();
|
||||
void CleanRing();
|
||||
char* inputBuffer;
|
||||
char outputBuffer[httpOutputBufferSize];
|
||||
int inputPointer;
|
||||
int inputLength;
|
||||
int outputPointer;
|
||||
bool writeEnabled;
|
||||
bool closePending;
|
||||
int8_t status;
|
||||
NetRing* netRingGetPointer;
|
||||
NetRing* netRingAddPointer;
|
||||
bool active;
|
||||
uint8_t sentPacketsOutstanding; // count of TCP packets we have sent that have not been acknowledged
|
||||
};
|
||||
|
||||
// This class handles serial I/O - typically via USB
|
||||
|
||||
|
@ -722,7 +616,6 @@ private:
|
|||
|
||||
void InitialiseInterrupts();
|
||||
int GetRawZHeight() const;
|
||||
void ResetZProbeMinSum();
|
||||
|
||||
// DRIVES
|
||||
|
||||
|
@ -747,7 +640,6 @@ private:
|
|||
volatile ZProbeAveragingFilter zProbeOnFilter; // Z probe readings we took with the IR turned on
|
||||
volatile ZProbeAveragingFilter zProbeOffFilter; // Z probe readings we took with the IR turned off
|
||||
volatile ThermistorAveragingFilter thermistorFilters[HEATERS]; // bed and extruder thermistor readings
|
||||
uint32_t zProbeMinSum; // minimum Z probe sums seen, used with ultrasonic probe
|
||||
|
||||
// AXES
|
||||
|
||||
|
@ -1088,17 +980,5 @@ inline void Platform::PopMessageIndent()
|
|||
|
||||
//***************************************************************************************
|
||||
|
||||
//queries the PHY for link status, true = link is up, false, link is down or there is some other error
|
||||
inline bool Network::LinkIsUp()
|
||||
{
|
||||
return status_link_up();
|
||||
}
|
||||
|
||||
inline bool Network::Active() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -304,6 +304,17 @@ void RepRap::SetDebug(int d)
|
|||
|
||||
char scratchString[STRING_LENGTH];
|
||||
|
||||
// For debug use
|
||||
void debugPrintf(const char* fmt, ...)
|
||||
{
|
||||
va_list p;
|
||||
va_start(p, fmt);
|
||||
vsnprintf(scratchString, ARRAY_SIZE(scratchString), fmt, p);
|
||||
va_end(p);
|
||||
scratchString[ARRAY_SIZE(scratchString) - 1] = 0;
|
||||
reprap.GetPlatform()->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
#if 0 // no longer used, we use snprinf or sncatf instead
|
||||
|
||||
// Float to a string.
|
||||
|
|
|
@ -27,12 +27,14 @@ Licence: GPL
|
|||
|
||||
// Warn of what's to come, so we can use pointers to classes...
|
||||
|
||||
class Network;
|
||||
class Platform;
|
||||
class Webserver;
|
||||
class GCodes;
|
||||
class Move;
|
||||
class Heat;
|
||||
class RepRap;
|
||||
class FileStore;
|
||||
|
||||
// A single instance of the RepRap class contains all the others
|
||||
|
||||
|
@ -40,8 +42,9 @@ extern RepRap reprap;
|
|||
|
||||
// Functions and globals not part of any class
|
||||
|
||||
void debugPrintf(const char* fmt, ...);
|
||||
int sncatf(char *dst, size_t len, const char* fmt, ...);
|
||||
#if 0 // n longer used
|
||||
#if 0 // no longer used
|
||||
char* ftoa(char *a, const float& f, int prec);
|
||||
#endif
|
||||
bool StringEndsWith(const char* string, const char* ending);
|
||||
|
@ -55,6 +58,7 @@ int StringContains(const char* string, const char* match);
|
|||
extern char scratchString[];
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "Network.h"
|
||||
#include "Platform.h"
|
||||
#include "Webserver.h"
|
||||
#include "GCodes.h"
|
||||
|
|
1316
Webserver.cpp
1316
Webserver.cpp
File diff suppressed because it is too large
Load diff
10
Webserver.h
10
Webserver.h
|
@ -53,7 +53,6 @@ class Webserver
|
|||
void Diagnostics();
|
||||
void SetPassword(const char* pw);
|
||||
void SetName(const char* nm);
|
||||
void ConnectionError();
|
||||
void HandleReply(const char *s, bool error);
|
||||
void AppendReply(const char* s);
|
||||
|
||||
|
@ -61,11 +60,9 @@ class Webserver
|
|||
|
||||
void ParseClientLine();
|
||||
void SendFile(const char* nameOfFileToSend);
|
||||
bool WriteBytes();
|
||||
void ParseQualifier();
|
||||
void CheckPassword();
|
||||
void LoadGcodeBuffer(const char* gc, bool convertWeb);
|
||||
void CloseClient();
|
||||
bool PrintHeadString();
|
||||
bool PrintLinkTable();
|
||||
void GetGCodeList();
|
||||
|
@ -84,8 +81,6 @@ class Webserver
|
|||
bool active;
|
||||
float lastTime;
|
||||
float longWait;
|
||||
FileStore* fileBeingSent;
|
||||
bool writing;
|
||||
bool receivingPost;
|
||||
char postBoundary[POST_LENGTH];
|
||||
int boundaryCount;
|
||||
|
@ -94,8 +89,6 @@ class Webserver
|
|||
bool postSeen;
|
||||
bool getSeen;
|
||||
bool clientLineIsBlank;
|
||||
float clientCloseTime;
|
||||
bool needToCloseClient;
|
||||
|
||||
char clientLine[STRING_LENGTH+2]; // 2 chars extra so we can append \n\0
|
||||
char clientRequest[STRING_LENGTH];
|
||||
|
@ -103,13 +96,12 @@ class Webserver
|
|||
char jsonResponse[STRING_LENGTH+1];
|
||||
char gcodeBuffer[gcodeBufLength];
|
||||
unsigned int gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer
|
||||
int jsonPointer;
|
||||
int clientLinePointer;
|
||||
bool gotPassword;
|
||||
char password[SHORT_STRING_LENGTH+1];
|
||||
char myName[SHORT_STRING_LENGTH+1];
|
||||
char gcodeReply[STRING_LENGTH+1];
|
||||
uint16_t seq; // reply sequence number, so that the client can tell if a reply is new or not
|
||||
uint16_t seq; // reply sequence number, so that the client can tell if a json reply is new or not
|
||||
};
|
||||
|
||||
|
||||
|
|
131
network/httpd.c
131
network/httpd.c
|
@ -61,21 +61,22 @@
|
|||
#include "lwip/src/include/lwip/tcp.h"
|
||||
#include "fs.h"
|
||||
|
||||
struct http_state {
|
||||
char *file;
|
||||
u16_t left;
|
||||
u8_t retries;
|
||||
struct http_state
|
||||
{
|
||||
// Receive fields
|
||||
struct pbuf *pb;
|
||||
// Transmit fields
|
||||
char *file;
|
||||
u16_t left;
|
||||
u8_t retries;
|
||||
};
|
||||
|
||||
// Prototypes for the RepRap functions in Platform.cpp that we
|
||||
// need to call.
|
||||
// Prototypes for the RepRap functions in Platform.cpp that we need to call.
|
||||
|
||||
void RepRapNetworkReceiveInput(char* ip, int length, void* pbuf, void* pcb, void* hs);
|
||||
void RepRapNetworkInputBufferReleased(void* pbuf);
|
||||
void RepRapNetworkConnectionError(void* h);
|
||||
void RepRapNetworkMessage(char* s);
|
||||
void RepRapNetworkSentPacketAcknowledged();
|
||||
bool RepRapNetworkHasALiveClient();
|
||||
void RepRapNetworkReceiveInput(const char* ip, int length, void* pcb, void* hs);
|
||||
void RepRapNetworkConnectionError(void* hs);
|
||||
void RepRapNetworkMessage(const char* s);
|
||||
void RepRapNetworkSentPacketAcknowledged(void *hs);
|
||||
|
||||
// Sanity check on initialisations.
|
||||
|
||||
|
@ -104,7 +105,7 @@ conn_err(void *arg, err_t err)
|
|||
static void
|
||||
close_conn(struct tcp_pcb *pcb, struct http_state *hs)
|
||||
{
|
||||
//RepRapNetworkMessage("close_conn called.\n");
|
||||
// RepRapNetworkMessage("close_conn called.\n");
|
||||
tcp_arg(pcb, NULL);
|
||||
tcp_sent(pcb, NULL);
|
||||
tcp_recv(pcb, NULL);
|
||||
|
@ -147,8 +148,6 @@ send_data(struct tcp_pcb *pcb, struct http_state *hs)
|
|||
tcp_output(pcb);
|
||||
hs->file += len;
|
||||
hs->left -= len;
|
||||
//if(hs->left <= 0)
|
||||
// RepRapNetworkAllowWriting();
|
||||
} else
|
||||
{
|
||||
RepRapNetworkMessage("send_data: error\n");
|
||||
|
@ -160,18 +159,19 @@ send_data(struct tcp_pcb *pcb, struct http_state *hs)
|
|||
static err_t
|
||||
http_poll(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
struct http_state *hs;
|
||||
struct http_state *hs = arg;
|
||||
|
||||
hs = arg;
|
||||
|
||||
/* printf("Polll\n");*/
|
||||
if (hs == NULL) {
|
||||
/* printf("Null, close\n");*/
|
||||
if (hs == NULL)
|
||||
{
|
||||
RepRapNetworkMessage("Null, abort\n");
|
||||
tcp_abort(pcb);
|
||||
return ERR_ABRT;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
++hs->retries;
|
||||
if (hs->retries == 4) {
|
||||
if (hs->retries == 4)
|
||||
{
|
||||
tcp_abort(pcb);
|
||||
return ERR_ABRT;
|
||||
}
|
||||
|
@ -186,12 +186,10 @@ http_poll(void *arg, struct tcp_pcb *pcb)
|
|||
static err_t
|
||||
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
struct http_state *hs;
|
||||
struct http_state *hs = arg;
|
||||
|
||||
LWIP_UNUSED_ARG(len);
|
||||
|
||||
hs = arg;
|
||||
|
||||
hs->retries = 0;
|
||||
|
||||
//RepRapNetworkMessage("..sent\n");
|
||||
|
@ -199,10 +197,11 @@ http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
|||
if (hs->left > 0)
|
||||
{
|
||||
send_data(pcb, hs);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if there is more to send
|
||||
RepRapNetworkSentPacketAcknowledged();
|
||||
RepRapNetworkSentPacketAcknowledged(hs);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
|
@ -210,26 +209,29 @@ http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// ReoRap calls this with data to send.
|
||||
// RepRap calls this with data to send.
|
||||
// A null transmission implies the end of the data to be sent.
|
||||
|
||||
void RepRapNetworkSendOutput(char* data, int length, void* pb, void* pc, void* h)
|
||||
void RepRapNetworkSendOutput(char* data, int length, void* pc, void* h)
|
||||
{
|
||||
struct pbuf* p = pb;
|
||||
struct tcp_pcb* pcb = pc;
|
||||
struct http_state* hs = h;
|
||||
|
||||
if(length <= 0)
|
||||
if (hs == 0)
|
||||
{
|
||||
//tcp_output(pcb);
|
||||
//pbuf_free(p);
|
||||
close_conn(pcb, hs);
|
||||
RepRapNetworkMessage("Attempt to write with null structure.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(hs == 0)
|
||||
if (hs->pb != NULL)
|
||||
{
|
||||
RepRapNetworkMessage("Attempt to write with null structure.\n");
|
||||
pbuf_free(hs->pb);
|
||||
hs->pb = NULL;
|
||||
}
|
||||
|
||||
if (length <= 0)
|
||||
{
|
||||
close_conn(pcb, hs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -237,30 +239,25 @@ void RepRapNetworkSendOutput(char* data, int length, void* pb, void* pc, void* h
|
|||
hs->left = length;
|
||||
hs->retries = 0;
|
||||
|
||||
if(pb != 0)
|
||||
{
|
||||
RepRapNetworkInputBufferReleased(p);
|
||||
pbuf_free(p);
|
||||
}
|
||||
send_data(pcb, hs);
|
||||
|
||||
//if(hs->left <= 0)
|
||||
//RepRapNetworkAllowWriting();
|
||||
|
||||
/* Tell TCP that we wish be to informed of data that has been
|
||||
successfully sent by a call to the http_sent() function. */
|
||||
/* Tell TCP that we wish be to informed of data that has been successfully sent by a call to the http_sent() function. */
|
||||
|
||||
tcp_sent(pcb, http_sent);
|
||||
}
|
||||
|
||||
|
||||
// Return 1 if sending is OK, i.e. there is no send in progress, else 0
|
||||
int RepRapNetworkCanSend(void *arg)
|
||||
{
|
||||
struct http_state *hs = arg;
|
||||
return hs->left <= 0;
|
||||
}
|
||||
|
||||
static err_t
|
||||
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
int i;
|
||||
struct http_state *hs;
|
||||
|
||||
hs = arg;
|
||||
struct http_state *hs = arg;
|
||||
|
||||
if (err == ERR_OK && p != NULL)
|
||||
{
|
||||
|
@ -269,16 +266,15 @@ http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
|||
|
||||
if (hs->file == NULL)
|
||||
{
|
||||
RepRapNetworkReceiveInput(p->payload, p->len, p, pcb, hs);
|
||||
} else
|
||||
hs->pb = p;
|
||||
RepRapNetworkReceiveInput(p->payload, p->len, pcb, hs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are already sending data on this connection, so not expecting any messages on it
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ERR_OK && p == NULL) {
|
||||
close_conn(pcb, hs);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -288,12 +284,6 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
{
|
||||
struct http_state *hs;
|
||||
|
||||
// This is a bit nasty. Fake an out of memory error to prevent new page
|
||||
// requests coming in while we are still sending the old ones.
|
||||
|
||||
if(RepRapNetworkHasALiveClient())
|
||||
return ERR_MEM;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_UNUSED_ARG(err);
|
||||
|
||||
|
@ -303,22 +293,22 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
|
||||
hs = (struct http_state *)mem_malloc(sizeof(struct http_state));
|
||||
|
||||
if (hs == NULL) {
|
||||
if (hs == NULL)
|
||||
{
|
||||
RepRapNetworkMessage("Out of memory!\n");
|
||||
return ERR_MEM;
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* Initialize the structure. */
|
||||
hs->pb = NULL;
|
||||
hs->file = NULL;
|
||||
hs->left = 0;
|
||||
hs->retries = 0;
|
||||
|
||||
/* Tell TCP that this is the structure we wish to be passed for our
|
||||
callbacks. */
|
||||
/* Tell TCP that this is the structure we wish to be passed for our callbacks. */
|
||||
tcp_arg(pcb, hs);
|
||||
|
||||
/* Tell TCP that we wish to be informed of incoming data by a call
|
||||
to the http_recv() function. */
|
||||
/* Tell TCP that we wish to be informed of incoming data by a call to the http_recv() function. */
|
||||
tcp_recv(pcb, http_recv);
|
||||
|
||||
tcp_err(pcb, conn_err);
|
||||
|
@ -326,6 +316,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
tcp_poll(pcb, http_poll, 4);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
// This function (is)x should be called only once at the start.
|
||||
|
@ -337,7 +328,9 @@ httpd_init(void)
|
|||
|
||||
initCount++;
|
||||
if(initCount > 1)
|
||||
{
|
||||
RepRapNetworkMessage("httpd_init() called more than once.\n");
|
||||
}
|
||||
|
||||
pcb = tcp_new();
|
||||
tcp_bind(pcb, IP_ADDR_ANY, 80);
|
||||
|
|
|
@ -104,7 +104,7 @@ a lot of data that needs to be copied, this should be set high. */
|
|||
#define MEMP_NUM_UDP_PCB 4
|
||||
|
||||
/* MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. */
|
||||
#define MEMP_NUM_TCP_PCB 2
|
||||
#define MEMP_NUM_TCP_PCB 6
|
||||
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. */
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 1
|
||||
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */
|
||||
|
|
Reference in a new issue