Skip to content

Instantly share code, notes, and snippets.

@n1ywb
Last active January 1, 2018 16:00
Show Gist options
  • Save n1ywb/450532cccc5d6233259be2a67ed8e23b to your computer and use it in GitHub Desktop.
Save n1ywb/450532cccc5d6233259be2a67ed8e23b to your computer and use it in GitHub Desktop.
feather m0 samd21 externally clocked counter
/*
WiFi Web Server
A simple web server that shows the value of the analog input pins.
using a WiFi shield.
This example is written for a network using WPA encryption. For
WEP or WPA, change the WiFi.begin() call accordingly.
Circuit:
* WiFi shield attached
* Analog inputs attached to pins A0 through A5 (optional)
created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi101.h>
#include <ArduinoJson.h>
#include <ArduinoHttpServer.h>
// #include <samd21g18a.h>
#include "wiring_private.h" // pinPeripheral() function
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
#define MAX(X,Y) (((X) > (Y)) ? (X) : (Y))
#include "types.h"
params_t params;
void dump_params(JsonObject& root) {
root["Kp"] = params.Kp;
root["Ki"] = params.Ki;
root["Kd"] = params.Kd;
root["Ko"] = params.Ko;
root["throttle_slew_rate"] = params.throttle_slew_rate;
root["mode"] = (int)params.mode;
root["speed_cmd"] = params.speed_cmd;
root["throttle_cmd"] = params.throttle_cmd;
root["speed"] = params.speed;
root["previous_speed"] = params.previous_speed;
root["throttle"] = params.throttle;
root["previous_throttle"] = params.previous_throttle;
root["vac"] = params.vac;
root["vcc"] = params.vcc;
root["amps"] = params.amps;
root["tc3_ovf_count"] = params.tc3_ovf_count;
root["current_tach"] = params.current_tach;
root["previous_tach"] = params.previous_tach;
root["pin20"] = digitalRead(20);
}
void load_params(JsonObject& root) {
params.Kp = root["Kp"];
params.Ki = root["Ki"];
params.Kd = root["Kd"];
params.Ko = root["Ko"];
params.throttle_slew_rate = root["throttle_slew_rate"];
params.mode = (tcs_mode_t)((int)root["mode"]);
params.speed_cmd = root["speed_cmd"];
params.throttle_cmd = root["throttle_cmd"];
}
WiFiServer server(80);
void setup_tc3() {
// Control loop ISR timer
// read 32khz from clock generator 1
// 2^15 / 2^8 / 4 == 32hz
// Set TC3 clock source to 32khz xtal and enable
Serial.println("disable tc3 irq");
NVIC_DisableIRQ(TC3_IRQn);
NVIC_ClearPendingIRQ(TC3_IRQn);
Serial.println("disable tc3");
REG_TC3_CTRLA = (uint16_t)(0);
while (REG_TC3_STATUS & TC_STATUS_SYNCBUSY) {}
Serial.println("disable tc3 clock");
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TCC2_TC3);
while (REG_GCLK_CLKCTRL & GCLK_CLKCTRL_CLKEN) {}
// Serial.println("set clock gen 8 divider");
// REG_GCLK_GENDIV = (uint32_t)(GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32));
Serial.println("enable clock gen 8, clock to 32khz xtal");
REG_GCLK_GENCTRL = (uint32_t)(GCLK_GENCTRL_ID(8) | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_GENEN);
Serial.println("enable tc3 clock");
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TCC2_TC3 | GCLK_CLKCTRL_GEN(8) | GCLK_CLKCTRL_CLKEN);
Serial.println("reset tc3");
REG_TC3_CTRLA = (uint16_t)(TC_CTRLA_SWRST);
while (REG_TC3_STATUS & TC_STATUS_SYNCBUSY) {
delay(1000);
Serial.println(REG_TC3_CTRLA & TC_CTRLA_SWRST);
}
Serial.println("enable tc3");
// 8 bit counter, / 4 prescale, enable
REG_TC3_CTRLA = (uint16_t)(TC_CTRLA_MODE_COUNT8 | TC_CTRLA_PRESCALER_DIV4 | TC_CTRLA_ENABLE);
Serial.println("enable tc3 interrupt");
// interrupt can be individually enabled by writing a one
// to the corresponding bit in the Interrupt Enable Set register (INTENSET),
REG_TC3_INTENSET = (uint8_t)(TC_INTENSET_OVF);
Serial.println(REG_TC3_INTENSET);
// Configure interrupt request
NVIC_SetPriority(TC3_IRQn, 0);
NVIC_EnableIRQ(TC3_IRQn);
}
void TC3_Handler(void) {
++params.tc3_ovf_count;
// control logic goes here
if (!TC4->COUNT32.STATUS.bit.SYNCBUSY) {
params.previous_tach = params.current_tach;
// this read is slow when the tc4 clock is slow; it's fast when the tc4 clock is disabled.
params.current_tach = REG_TC4_COUNT32_COUNT;
REG_TC4_READREQ = (uint16_t)(TC_READREQ_RREQ | TC_READREQ_ADDR(TC_COUNT32_COUNT_OFFSET));
}
REG_TC3_INTFLAG = (uint8_t)(TC_INTFLAG_OVF);
}
void setup_tc4() {
// Tachometer pulse counter; 3/rev
// signal path:
// port -> gclock io -> gclock controller -> ahb-apb bridge A -> hi speed bus matrix -> ahb-apb bridge C -> TC4/5
// gclock detail:
// gclk io -> controller -> generator -> divider/masker -> multiplexer -> gate -> gclk_peripheral -> peripheral
// Using the TC’s I/O lines requires the I/O pins to be configured. Refer to “PORT” on page 379 for details.
// REG_PORTA
// configure arduino pin 20 uc pin 31 multiplex for gclkio[6]
// pin 20 drives clock 6
pinMode(20, INPUT_PULLUP);
pinPeripheral(20, PIO_AC_CLK);
Serial.println("disable tc4");
TC4->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
while (REG_TC4_STATUS & TC_STATUS_SYNCBUSY);
Serial.println("disable tc5");
TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
while (TC5->COUNT16.STATUS.bit.SYNCBUSY);
Serial.println("disable tc5 irq");
NVIC_DisableIRQ(TC5_IRQn);
NVIC_ClearPendingIRQ(TC5_IRQn);
NVIC_DisableIRQ(TC4_IRQn);
NVIC_ClearPendingIRQ(TC4_IRQn);
Serial.println("disable tc4 clock");
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5);
while (GCLK->STATUS.bit.SYNCBUSY);
Serial.println("enable tc4 clock");
// Set clock gen 6 clock source to gclk_io[6] and enable
REG_GCLK_GENCTRL = (uint32_t)(GCLK_GENCTRL_ID(6) | GCLK_GENCTRL_SRC_GCLKIN | GCLK_GENCTRL_GENEN);
while (GCLK->STATUS.bit.SYNCBUSY);
// Clock TC4 to cpu during config
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5 | GCLK_CLKCTRL_GEN(0) | GCLK_CLKCTRL_CLKEN);
while (GCLK->STATUS.bit.SYNCBUSY);
//z The mode (8, 16 or 32 bits) of the TC must be selected in the TC Mode bit group in the Control A register
//(CTRLA.MODE). The default mode is 16 bits
// is this slow?
// REG_TC4_READREQ = (uint16_t)(TC_READREQ_RCONT | TC_READREQ_ADDR(TC_COUNT32_COUNT_OFFSET));
Serial.println("reset tc5");
REG_TC5_CTRLA = (uint16_t)(TC_CTRLA_SWRST);
while (TC5->COUNT16.STATUS.bit.SYNCBUSY) {
delay(1000);
Serial.println(REG_TC5_CTRLA & TC_CTRLA_SWRST);
}
Serial.println("reset tc4");
REG_TC4_CTRLA = (uint16_t)(TC_CTRLA_SWRST);
while (TC4->COUNT16.STATUS.bit.SYNCBUSY) {
delay(1000);
Serial.println(REG_TC4_CTRLA & TC_CTRLA_SWRST);
}
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5);
while (GCLK->STATUS.bit.SYNCBUSY);
// return;
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5 | GCLK_CLKCTRL_GEN(6) | GCLK_CLKCTRL_CLKEN);
while (GCLK->STATUS.bit.SYNCBUSY);
Serial.println("enable tc4");
REG_TC4_CTRLA = (uint16_t)(TC_CTRLA_MODE_COUNT32 | TC_CTRLA_ENABLE);
}
void setup() {
WiFi.setPins(8,7,4,2);
//Initialize serial and wait for port to open:
Serial.begin(9600);
delay(2000);
// while (!Serial) {
// ; // wait for serial port to connect. Needed for native USB port only
// }
setup_tc4();
setup_tc3();
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(5000);
}
server.begin();
// you're connected now, so print out the status:
printWiFiStatus();
}
void sendreply(Client& client) {
const size_t bufferSize = JSON_OBJECT_SIZE(18);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& root = jsonBuffer.createObject();
dump_params(root);
ArduinoHttpServer::StreamHttpReply httpReply(client, "application/json");
while(client.read()>=0);
String httpErrorReply("HTTP/1.1 200\r\n");
httpErrorReply += "Connection: close\r\n";
// httpErrorReply += "Content-Length: ";
// httpErrorReply += data.length(); httpErrorReply += "\r\n";
httpErrorReply += "Content-Type: application/json\r\n";
httpErrorReply += "\r\n";
// httpErrorReply += data;
client.print(httpErrorReply);
root.printTo(client);
}
void loop() {
// listen for incoming clients
WiFiClient client = server.available();
if (client) {
Serial.println("new client");
while (client.connected()) {
if (client.available()) {
ArduinoHttpServer::StreamHttpRequest<1023> httpRequest(client);
// Parse the request.
if (httpRequest.readRequest())
{
// Use the information you like they way you like.
// Retrieve HTTP resource / URL requested
// Retrieve 2nd part of HTTP resource.
// E.g.: "on" from "/api/sensors/on"
// Serial.println( httpRequest.getResource()[2] );
// Retrieve HTTP method.
// E.g.: GET / PUT / HEAD / DELETE / POST
ArduinoHttpServer::MethodEnum method( ArduinoHttpServer::MethodInvalid );
method = httpRequest.getMethod();
Serial.println( httpRequest.getResource().toString() );
if( method == ArduinoHttpServer::MethodGet )
{
Serial.println("GET");
sendreply(client);
client.stop();
break;
}
else if( method == ArduinoHttpServer::MethodPost )
{
Serial.println("POST");
const size_t bufferSize = JSON_OBJECT_SIZE(18) + 300;
DynamicJsonBuffer jsonBuffer(bufferSize);
Serial.println(httpRequest.getBody());
JsonObject& root2 = jsonBuffer.parseObject(httpRequest.getBody());
if (root2.success()) {
load_params(root2);
sendreply(client);
}
else {
Serial.println("json decoding error");
}
client.stop();
break;
}
}
else
{
// HTTP parsing failed. Client did not provide correct HTTP data or
// client requested an unsupported feature.
ArduinoHttpServer::StreamHttpErrorReply httpReply(client, httpRequest.getContentType());
httpReply.send(httpRequest.getErrorDescrition());
client.stop();
break;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
void printWiFiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment