Compare commits

...

3 commits

Author SHA1 Message Date
Doxygen CI
45c019a179 Deploy docs to GitHub Pages from commit b5944766cb
Commit: b5944766cb
GitHub Actions run: 4640175227
2023-04-07 17:47:19 +00:00
caternuson
a6399c6884 remove github dir 2023-04-07 10:17:25 -07:00
caternuson
94376be457 gh-pages set up 2023-04-07 10:16:14 -07:00
50 changed files with 2980 additions and 4312 deletions

View file

@ -1,46 +0,0 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View file

@ -1,26 +0,0 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

View file

@ -1,32 +0,0 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py main_platforms
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit CAN Arduino Library"
run: bash ci/doxy_gen_and_deploy.sh

1
.nojekyll Normal file
View file

@ -0,0 +1 @@

View file

@ -1,4 +0,0 @@
# Adafruit CAN Library
This is an Arduino library for the supporting boards with native CAN peripherals.

View file

@ -1,62 +0,0 @@
/*
* Adafruit Feather M4 CAN Receiver Callback Example
*/
#include <CANSAME5x.h>
CANSAME5x CAN;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("CAN Receiver Callback");
// start the CAN bus at 250 kbps
if (!CAN.begin(250E3)) {
Serial.println("Starting CAN failed!");
while (1);
}
// register the receive callback
CAN.onReceive(onReceive);
}
void loop() {
// do nothing
}
void onReceive(int packetSize) {
// received a packet
Serial.print("Received ");
if (CAN.packetExtended()) {
Serial.print("extended ");
}
if (CAN.packetRtr()) {
// Remote transmission request, packet contains no data
Serial.print("RTR ");
}
Serial.print("packet with id 0x");
Serial.print(CAN.packetId(), HEX);
if (CAN.packetRtr()) {
Serial.print(" and requested length ");
Serial.println(CAN.packetDlc());
} else {
Serial.print(" and length ");
Serial.println(packetSize);
// only print packet data for non-RTR packets
while (CAN.available()) {
Serial.print((char)CAN.read());
}
Serial.println();
}
Serial.println();
}

View file

@ -1,63 +0,0 @@
/*
* Adafruit Feather M4 CAN Receiver Example
*/
#include <CANSAME5x.h>
CANSAME5x CAN;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("CAN Receiver");
pinMode(PIN_CAN_STANDBY, OUTPUT);
digitalWrite(PIN_CAN_STANDBY, false); // turn off STANDBY
pinMode(PIN_CAN_BOOSTEN, OUTPUT);
digitalWrite(PIN_CAN_BOOSTEN, true); // turn on booster
// start the CAN bus at 250 kbps
if (!CAN.begin(250000)) {
Serial.println("Starting CAN failed!");
while (1);
}
}
void loop() {
// try to parse packet
int packetSize = CAN.parsePacket();
if (packetSize) {
// received a packet
Serial.print("Received ");
if (CAN.packetExtended()) {
Serial.print("extended ");
}
if (CAN.packetRtr()) {
// Remote transmission request, packet contains no data
Serial.print("RTR ");
}
Serial.print("packet with id 0x");
Serial.print(CAN.packetId(), HEX);
if (CAN.packetRtr()) {
Serial.print(" and requested length ");
Serial.println(CAN.packetDlc());
} else {
Serial.print(" and length ");
Serial.println(packetSize);
// only print packet data for non-RTR packets
while (CAN.available()) {
Serial.print((char)CAN.read());
}
Serial.println();
}
Serial.println();
}
}

View file

@ -1,56 +0,0 @@
/*
* Adafruit Feather M4 CAN Sender Example
*/
#include <CANSAME5x.h>
CANSAME5x CAN;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("CAN Sender");
pinMode(PIN_CAN_STANDBY, OUTPUT);
digitalWrite(PIN_CAN_STANDBY, false); // turn off STANDBY
pinMode(PIN_CAN_BOOSTEN, OUTPUT);
digitalWrite(PIN_CAN_BOOSTEN, true); // turn on booster
// start the CAN bus at 250 kbps
if (!CAN.begin(250000)) {
Serial.println("Starting CAN failed!");
while (1);
}
}
void loop() {
// send packet: id is 11 bits, packet can contain up to 8 bytes of data
Serial.print("Sending packet ... ");
CAN.beginPacket(0x12);
CAN.write('h');
CAN.write('e');
CAN.write('l');
CAN.write('l');
CAN.write('o');
CAN.endPacket();
Serial.println("done");
delay(1000);
// send extended packet: id is 29 bits, packet can contain up to 8 bytes of data
Serial.print("Sending extended packet ... ");
CAN.beginExtendedPacket(0xabcdef);
CAN.write('w');
CAN.write('o');
CAN.write('r');
CAN.write('l');
CAN.write('d');
CAN.endPacket();
Serial.println("done");
delay(1000);
}

BIN
html/bc_s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

BIN
html/bdwn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

BIN
html/closed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

BIN
html/doc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

1596
html/doxygen.css Normal file

File diff suppressed because it is too large Load diff

BIN
html/doxygen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

97
html/dynsections.js Normal file
View file

@ -0,0 +1,97 @@
function toggleVisibility(linkObj)
{
var base = $(linkObj).attr('id');
var summary = $('#'+base+'-summary');
var content = $('#'+base+'-content');
var trigger = $('#'+base+'-trigger');
var src=$(trigger).attr('src');
if (content.is(':visible')===true) {
content.hide();
summary.show();
$(linkObj).addClass('closed').removeClass('opened');
$(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
} else {
content.show();
summary.hide();
$(linkObj).removeClass('closed').addClass('opened');
$(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
}
return false;
}
function updateStripes()
{
$('table.directory tr').
removeClass('even').filter(':visible:even').addClass('even');
}
function toggleLevel(level)
{
$('table.directory tr').each(function() {
var l = this.id.split('_').length-1;
var i = $('#img'+this.id.substring(3));
var a = $('#arr'+this.id.substring(3));
if (l<level+1) {
i.removeClass('iconfopen iconfclosed').addClass('iconfopen');
a.html('&#9660;');
$(this).show();
} else if (l==level+1) {
i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');
a.html('&#9658;');
$(this).show();
} else {
$(this).hide();
}
});
updateStripes();
}
function toggleFolder(id)
{
// the clicked row
var currentRow = $('#row_'+id);
// all rows after the clicked row
var rows = currentRow.nextAll("tr");
var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
// only match elements AFTER this one (can't hide elements before)
var childRows = rows.filter(function() { return this.id.match(re); });
// first row is visible we are HIDING
if (childRows.filter(':first').is(':visible')===true) {
// replace down arrow by right arrow for current row
var currentRowSpans = currentRow.find("span");
currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
currentRowSpans.filter(".arrow").html('&#9658;');
rows.filter("[id^=row_"+id+"]").hide(); // hide all children
} else { // we are SHOWING
// replace right arrow by down arrow for current row
var currentRowSpans = currentRow.find("span");
currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");
currentRowSpans.filter(".arrow").html('&#9660;');
// replace down arrows by right arrows for child rows
var childRowsSpans = childRows.find("span");
childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
childRowsSpans.filter(".arrow").html('&#9658;');
childRows.show(); //show all children
}
updateStripes();
}
function toggleInherit(id)
{
var rows = $('tr.inherit.'+id);
var img = $('tr.inherit_header.'+id+' img');
var src = $(img).attr('src');
if (rows.filter(':first').is(':visible')===true) {
rows.css('display','none');
$(img).attr('src',src.substring(0,src.length-8)+'closed.png');
} else {
rows.css('display','table-row'); // using show() causes jump in firefox
$(img).attr('src',src.substring(0,src.length-10)+'open.png');
}
}

BIN
html/folderclosed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

BIN
html/folderopen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

73
html/index.html Normal file
View file

@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Adafruit CAN Arduino Library: Main Page</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">Adafruit CAN Arduino Library
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="headertitle">
<div class="title">Adafruit CAN Arduino Library Documentation</div> </div>
</div><!--header-->
<div class="contents">
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
</body>
</html>

87
html/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

26
html/menu.js Normal file
View file

@ -0,0 +1,26 @@
function initMenu(relPath,searchEnabled,serverSide,searchPage,search) {
function makeTree(data,relPath) {
var result='';
if ('children' in data) {
result+='<ul>';
for (var i in data.children) {
result+='<li><a href="'+relPath+data.children[i].url+'">'+
data.children[i].text+'</a>'+
makeTree(data.children[i],relPath)+'</li>';
}
result+='</ul>';
}
return result;
}
$('#main-nav').append(makeTree(menudata,relPath));
$('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu');
if (searchEnabled) {
if (serverSide) {
$('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><div class="left"><form id="FSearchBox" action="'+searchPage+'" method="get"><img id="MSearchSelect" src="'+relPath+'search/mag.png" alt=""/><input type="text" id="MSearchField" name="query" value="'+search+'" size="20" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)"></form></div><div class="right"></div></div></li>');
} else {
$('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><span class="left"><img id="MSearchSelect" src="'+relPath+'search/mag_sel.png" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()" alt=""/><input type="text" id="MSearchField" value="'+search+'" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)" onkeyup="searchBox.OnSearchFieldChange(event)"/></span><span class="right"><a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="'+relPath+'search/close.png" alt=""/></a></span></div></li>');
}
}
$('#main-menu').smartmenus();
}

2
html/menudata.js Normal file
View file

@ -0,0 +1,2 @@
var menudata={children:[
{text:"Main Page",url:"index.html"}]}

BIN
html/nav_f.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

BIN
html/nav_g.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

BIN
html/nav_h.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

BIN
html/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

BIN
html/search/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

BIN
html/search/mag_sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

View file

@ -0,0 +1,12 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</body>
</html>

271
html/search/search.css Normal file
View file

@ -0,0 +1,271 @@
/*---------------- Search Box */
#FSearchBox {
float: left;
}
#MSearchBox {
white-space : nowrap;
float: none;
margin-top: 8px;
right: 0px;
width: 170px;
height: 24px;
z-index: 102;
}
#MSearchBox .left
{
display:block;
position:absolute;
left:10px;
width:20px;
height:19px;
background:url('search_l.png') no-repeat;
background-position:right;
}
#MSearchSelect {
display:block;
position:absolute;
width:20px;
height:19px;
}
.left #MSearchSelect {
left:4px;
}
.right #MSearchSelect {
right:5px;
}
#MSearchField {
display:block;
position:absolute;
height:19px;
background:url('search_m.png') repeat-x;
border:none;
width:115px;
margin-left:20px;
padding-left:4px;
color: #909090;
outline: none;
font: 9pt Arial, Verdana, sans-serif;
-webkit-border-radius: 0px;
}
#FSearchBox #MSearchField {
margin-left:15px;
}
#MSearchBox .right {
display:block;
position:absolute;
right:10px;
top:8px;
width:20px;
height:19px;
background:url('search_r.png') no-repeat;
background-position:left;
}
#MSearchClose {
display: none;
position: absolute;
top: 4px;
background : none;
border: none;
margin: 0px 4px 0px 0px;
padding: 0px 0px;
outline: none;
}
.left #MSearchClose {
left: 6px;
}
.right #MSearchClose {
right: 2px;
}
.MSearchBoxActive #MSearchField {
color: #000000;
}
/*---------------- Search filter selection */
#MSearchSelectWindow {
display: none;
position: absolute;
left: 0; top: 0;
border: 1px solid #90A5CE;
background-color: #F9FAFC;
z-index: 10001;
padding-top: 4px;
padding-bottom: 4px;
-moz-border-radius: 4px;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
-webkit-border-bottom-left-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
}
.SelectItem {
font: 8pt Arial, Verdana, sans-serif;
padding-left: 2px;
padding-right: 12px;
border: 0px;
}
span.SelectionMark {
margin-right: 4px;
font-family: monospace;
outline-style: none;
text-decoration: none;
}
a.SelectItem {
display: block;
outline-style: none;
color: #000000;
text-decoration: none;
padding-left: 6px;
padding-right: 12px;
}
a.SelectItem:focus,
a.SelectItem:active {
color: #000000;
outline-style: none;
text-decoration: none;
}
a.SelectItem:hover {
color: #FFFFFF;
background-color: #3D578C;
outline-style: none;
text-decoration: none;
cursor: pointer;
display: block;
}
/*---------------- Search results window */
iframe#MSearchResults {
width: 60ex;
height: 15em;
}
#MSearchResultsWindow {
display: none;
position: absolute;
left: 0; top: 0;
border: 1px solid #000;
background-color: #EEF1F7;
z-index:10000;
}
/* ----------------------------------- */
#SRIndex {
clear:both;
padding-bottom: 15px;
}
.SREntry {
font-size: 10pt;
padding-left: 1ex;
}
.SRPage .SREntry {
font-size: 8pt;
padding: 1px 5px;
}
body.SRPage {
margin: 5px 2px;
}
.SRChildren {
padding-left: 3ex; padding-bottom: .5em
}
.SRPage .SRChildren {
display: none;
}
.SRSymbol {
font-weight: bold;
color: #425E97;
font-family: Arial, Verdana, sans-serif;
text-decoration: none;
outline: none;
}
a.SRScope {
display: block;
color: #425E97;
font-family: Arial, Verdana, sans-serif;
text-decoration: none;
outline: none;
}
a.SRSymbol:focus, a.SRSymbol:active,
a.SRScope:focus, a.SRScope:active {
text-decoration: underline;
}
span.SRScope {
padding-left: 4px;
}
.SRPage .SRStatus {
padding: 2px 5px;
font-size: 8pt;
font-style: italic;
}
.SRResult {
display: none;
}
DIV.searchresults {
margin-left: 10px;
margin-right: 10px;
}
/*---------------- External search page results */
.searchresult {
background-color: #F0F3F8;
}
.pages b {
color: white;
padding: 5px 5px 3px 5px;
background-image: url("../tab_a.png");
background-repeat: repeat-x;
text-shadow: 0 1px 1px #000000;
}
.pages {
line-height: 17px;
margin-left: 4px;
text-decoration: none;
}
.hl {
font-weight: bold;
}
#searchresults {
margin-bottom: 20px;
}
.searchpages {
margin-top: 10px;
}

791
html/search/search.js Normal file
View file

@ -0,0 +1,791 @@
function convertToId(search)
{
var result = '';
for (i=0;i<search.length;i++)
{
var c = search.charAt(i);
var cn = c.charCodeAt(0);
if (c.match(/[a-z0-9\u0080-\uFFFF]/))
{
result+=c;
}
else if (cn<16)
{
result+="_0"+cn.toString(16);
}
else
{
result+="_"+cn.toString(16);
}
}
return result;
}
function getXPos(item)
{
var x = 0;
if (item.offsetWidth)
{
while (item && item!=document.body)
{
x += item.offsetLeft;
item = item.offsetParent;
}
}
return x;
}
function getYPos(item)
{
var y = 0;
if (item.offsetWidth)
{
while (item && item!=document.body)
{
y += item.offsetTop;
item = item.offsetParent;
}
}
return y;
}
/* A class handling everything associated with the search panel.
Parameters:
name - The name of the global variable that will be
storing this instance. Is needed to be able to set timeouts.
resultPath - path to use for external files
*/
function SearchBox(name, resultsPath, inFrame, label)
{
if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
// ---------- Instance variables
this.name = name;
this.resultsPath = resultsPath;
this.keyTimeout = 0;
this.keyTimeoutLength = 500;
this.closeSelectionTimeout = 300;
this.lastSearchValue = "";
this.lastResultsPage = "";
this.hideTimeout = 0;
this.searchIndex = 0;
this.searchActive = false;
this.insideFrame = inFrame;
this.searchLabel = label;
// ----------- DOM Elements
this.DOMSearchField = function()
{ return document.getElementById("MSearchField"); }
this.DOMSearchSelect = function()
{ return document.getElementById("MSearchSelect"); }
this.DOMSearchSelectWindow = function()
{ return document.getElementById("MSearchSelectWindow"); }
this.DOMPopupSearchResults = function()
{ return document.getElementById("MSearchResults"); }
this.DOMPopupSearchResultsWindow = function()
{ return document.getElementById("MSearchResultsWindow"); }
this.DOMSearchClose = function()
{ return document.getElementById("MSearchClose"); }
this.DOMSearchBox = function()
{ return document.getElementById("MSearchBox"); }
// ------------ Event Handlers
// Called when focus is added or removed from the search field.
this.OnSearchFieldFocus = function(isActive)
{
this.Activate(isActive);
}
this.OnSearchSelectShow = function()
{
var searchSelectWindow = this.DOMSearchSelectWindow();
var searchField = this.DOMSearchSelect();
if (this.insideFrame)
{
var left = getXPos(searchField);
var top = getYPos(searchField);
left += searchField.offsetWidth + 6;
top += searchField.offsetHeight;
// show search selection popup
searchSelectWindow.style.display='block';
left -= searchSelectWindow.offsetWidth;
searchSelectWindow.style.left = left + 'px';
searchSelectWindow.style.top = top + 'px';
}
else
{
var left = getXPos(searchField);
var top = getYPos(searchField);
top += searchField.offsetHeight;
// show search selection popup
searchSelectWindow.style.display='block';
searchSelectWindow.style.left = left + 'px';
searchSelectWindow.style.top = top + 'px';
}
// stop selection hide timer
if (this.hideTimeout)
{
clearTimeout(this.hideTimeout);
this.hideTimeout=0;
}
return false; // to avoid "image drag" default event
}
this.OnSearchSelectHide = function()
{
this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
this.closeSelectionTimeout);
}
// Called when the content of the search field is changed.
this.OnSearchFieldChange = function(evt)
{
if (this.keyTimeout) // kill running timer
{
clearTimeout(this.keyTimeout);
this.keyTimeout = 0;
}
var e = (evt) ? evt : window.event; // for IE
if (e.keyCode==40 || e.keyCode==13)
{
if (e.shiftKey==1)
{
this.OnSearchSelectShow();
var win=this.DOMSearchSelectWindow();
for (i=0;i<win.childNodes.length;i++)
{
var child = win.childNodes[i]; // get span within a
if (child.className=='SelectItem')
{
child.focus();
return;
}
}
return;
}
else if (window.frames.MSearchResults.searchResults)
{
var elem = window.frames.MSearchResults.searchResults.NavNext(0);
if (elem) elem.focus();
}
}
else if (e.keyCode==27) // Escape out of the search field
{
this.DOMSearchField().blur();
this.DOMPopupSearchResultsWindow().style.display = 'none';
this.DOMSearchClose().style.display = 'none';
this.lastSearchValue = '';
this.Activate(false);
return;
}
// strip whitespaces
var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
if (searchValue != this.lastSearchValue) // search value has changed
{
if (searchValue != "") // non-empty search
{
// set timer for search update
this.keyTimeout = setTimeout(this.name + '.Search()',
this.keyTimeoutLength);
}
else // empty search field
{
this.DOMPopupSearchResultsWindow().style.display = 'none';
this.DOMSearchClose().style.display = 'none';
this.lastSearchValue = '';
}
}
}
this.SelectItemCount = function(id)
{
var count=0;
var win=this.DOMSearchSelectWindow();
for (i=0;i<win.childNodes.length;i++)
{
var child = win.childNodes[i]; // get span within a
if (child.className=='SelectItem')
{
count++;
}
}
return count;
}
this.SelectItemSet = function(id)
{
var i,j=0;
var win=this.DOMSearchSelectWindow();
for (i=0;i<win.childNodes.length;i++)
{
var child = win.childNodes[i]; // get span within a
if (child.className=='SelectItem')
{
var node = child.firstChild;
if (j==id)
{
node.innerHTML='&#8226;';
}
else
{
node.innerHTML='&#160;';
}
j++;
}
}
}
// Called when an search filter selection is made.
// set item with index id as the active item
this.OnSelectItem = function(id)
{
this.searchIndex = id;
this.SelectItemSet(id);
var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
if (searchValue!="" && this.searchActive) // something was found -> do a search
{
this.Search();
}
}
this.OnSearchSelectKey = function(evt)
{
var e = (evt) ? evt : window.event; // for IE
if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
{
this.searchIndex++;
this.OnSelectItem(this.searchIndex);
}
else if (e.keyCode==38 && this.searchIndex>0) // Up
{
this.searchIndex--;
this.OnSelectItem(this.searchIndex);
}
else if (e.keyCode==13 || e.keyCode==27)
{
this.OnSelectItem(this.searchIndex);
this.CloseSelectionWindow();
this.DOMSearchField().focus();
}
return false;
}
// --------- Actions
// Closes the results window.
this.CloseResultsWindow = function()
{
this.DOMPopupSearchResultsWindow().style.display = 'none';
this.DOMSearchClose().style.display = 'none';
this.Activate(false);
}
this.CloseSelectionWindow = function()
{
this.DOMSearchSelectWindow().style.display = 'none';
}
// Performs a search.
this.Search = function()
{
this.keyTimeout = 0;
// strip leading whitespace
var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
var code = searchValue.toLowerCase().charCodeAt(0);
var idxChar = searchValue.substr(0, 1).toLowerCase();
if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
{
idxChar = searchValue.substr(0, 2);
}
var resultsPage;
var resultsPageWithSearch;
var hasResultsPage;
var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
if (idx!=-1)
{
var hexCode=idx.toString(16);
resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
hasResultsPage = true;
}
else // nothing available for this search term
{
resultsPage = this.resultsPath + '/nomatches.html';
resultsPageWithSearch = resultsPage;
hasResultsPage = false;
}
window.frames.MSearchResults.location = resultsPageWithSearch;
var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
if (domPopupSearchResultsWindow.style.display!='block')
{
var domSearchBox = this.DOMSearchBox();
this.DOMSearchClose().style.display = 'inline';
if (this.insideFrame)
{
var domPopupSearchResults = this.DOMPopupSearchResults();
domPopupSearchResultsWindow.style.position = 'relative';
domPopupSearchResultsWindow.style.display = 'block';
var width = document.body.clientWidth - 8; // the -8 is for IE :-(
domPopupSearchResultsWindow.style.width = width + 'px';
domPopupSearchResults.style.width = width + 'px';
}
else
{
var domPopupSearchResults = this.DOMPopupSearchResults();
var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1;
domPopupSearchResultsWindow.style.display = 'block';
left -= domPopupSearchResults.offsetWidth;
domPopupSearchResultsWindow.style.top = top + 'px';
domPopupSearchResultsWindow.style.left = left + 'px';
}
}
this.lastSearchValue = searchValue;
this.lastResultsPage = resultsPage;
}
// -------- Activation Functions
// Activates or deactivates the search panel, resetting things to
// their default values if necessary.
this.Activate = function(isActive)
{
if (isActive || // open it
this.DOMPopupSearchResultsWindow().style.display == 'block'
)
{
this.DOMSearchBox().className = 'MSearchBoxActive';
var searchField = this.DOMSearchField();
if (searchField.value == this.searchLabel) // clear "Search" term upon entry
{
searchField.value = '';
this.searchActive = true;
}
}
else if (!isActive) // directly remove the panel
{
this.DOMSearchBox().className = 'MSearchBoxInactive';
this.DOMSearchField().value = this.searchLabel;
this.searchActive = false;
this.lastSearchValue = ''
this.lastResultsPage = '';
}
}
}
// -----------------------------------------------------------------------
// The class that handles everything on the search results page.
function SearchResults(name)
{
// The number of matches from the last run of <Search()>.
this.lastMatchCount = 0;
this.lastKey = 0;
this.repeatOn = false;
// Toggles the visibility of the passed element ID.
this.FindChildElement = function(id)
{
var parentElement = document.getElementById(id);
var element = parentElement.firstChild;
while (element && element!=parentElement)
{
if (element.nodeName == 'DIV' && element.className == 'SRChildren')
{
return element;
}
if (element.nodeName == 'DIV' && element.hasChildNodes())
{
element = element.firstChild;
}
else if (element.nextSibling)
{
element = element.nextSibling;
}
else
{
do
{
element = element.parentNode;
}
while (element && element!=parentElement && !element.nextSibling);
if (element && element!=parentElement)
{
element = element.nextSibling;
}
}
}
}
this.Toggle = function(id)
{
var element = this.FindChildElement(id);
if (element)
{
if (element.style.display == 'block')
{
element.style.display = 'none';
}
else
{
element.style.display = 'block';
}
}
}
// Searches for the passed string. If there is no parameter,
// it takes it from the URL query.
//
// Always returns true, since other documents may try to call it
// and that may or may not be possible.
this.Search = function(search)
{
if (!search) // get search word from URL
{
search = window.location.search;
search = search.substring(1); // Remove the leading '?'
search = unescape(search);
}
search = search.replace(/^ +/, ""); // strip leading spaces
search = search.replace(/ +$/, ""); // strip trailing spaces
search = search.toLowerCase();
search = convertToId(search);
var resultRows = document.getElementsByTagName("div");
var matches = 0;
var i = 0;
while (i < resultRows.length)
{
var row = resultRows.item(i);
if (row.className == "SRResult")
{
var rowMatchName = row.id.toLowerCase();
rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
if (search.length<=rowMatchName.length &&
rowMatchName.substr(0, search.length)==search)
{
row.style.display = 'block';
matches++;
}
else
{
row.style.display = 'none';
}
}
i++;
}
document.getElementById("Searching").style.display='none';
if (matches == 0) // no results
{
document.getElementById("NoMatches").style.display='block';
}
else // at least one result
{
document.getElementById("NoMatches").style.display='none';
}
this.lastMatchCount = matches;
return true;
}
// return the first item with index index or higher that is visible
this.NavNext = function(index)
{
var focusItem;
while (1)
{
var focusName = 'Item'+index;
focusItem = document.getElementById(focusName);
if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
{
break;
}
else if (!focusItem) // last element
{
break;
}
focusItem=null;
index++;
}
return focusItem;
}
this.NavPrev = function(index)
{
var focusItem;
while (1)
{
var focusName = 'Item'+index;
focusItem = document.getElementById(focusName);
if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
{
break;
}
else if (!focusItem) // last element
{
break;
}
focusItem=null;
index--;
}
return focusItem;
}
this.ProcessKeys = function(e)
{
if (e.type == "keydown")
{
this.repeatOn = false;
this.lastKey = e.keyCode;
}
else if (e.type == "keypress")
{
if (!this.repeatOn)
{
if (this.lastKey) this.repeatOn = true;
return false; // ignore first keypress after keydown
}
}
else if (e.type == "keyup")
{
this.lastKey = 0;
this.repeatOn = false;
}
return this.lastKey!=0;
}
this.Nav = function(evt,itemIndex)
{
var e = (evt) ? evt : window.event; // for IE
if (e.keyCode==13) return true;
if (!this.ProcessKeys(e)) return false;
if (this.lastKey==38) // Up
{
var newIndex = itemIndex-1;
var focusItem = this.NavPrev(newIndex);
if (focusItem)
{
var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
if (child && child.style.display == 'block') // children visible
{
var n=0;
var tmpElem;
while (1) // search for last child
{
tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
if (tmpElem)
{
focusItem = tmpElem;
}
else // found it!
{
break;
}
n++;
}
}
}
if (focusItem)
{
focusItem.focus();
}
else // return focus to search field
{
parent.document.getElementById("MSearchField").focus();
}
}
else if (this.lastKey==40) // Down
{
var newIndex = itemIndex+1;
var focusItem;
var item = document.getElementById('Item'+itemIndex);
var elem = this.FindChildElement(item.parentNode.parentNode.id);
if (elem && elem.style.display == 'block') // children visible
{
focusItem = document.getElementById('Item'+itemIndex+'_c0');
}
if (!focusItem) focusItem = this.NavNext(newIndex);
if (focusItem) focusItem.focus();
}
else if (this.lastKey==39) // Right
{
var item = document.getElementById('Item'+itemIndex);
var elem = this.FindChildElement(item.parentNode.parentNode.id);
if (elem) elem.style.display = 'block';
}
else if (this.lastKey==37) // Left
{
var item = document.getElementById('Item'+itemIndex);
var elem = this.FindChildElement(item.parentNode.parentNode.id);
if (elem) elem.style.display = 'none';
}
else if (this.lastKey==27) // Escape
{
parent.searchBox.CloseResultsWindow();
parent.document.getElementById("MSearchField").focus();
}
else if (this.lastKey==13) // Enter
{
return true;
}
return false;
}
this.NavChild = function(evt,itemIndex,childIndex)
{
var e = (evt) ? evt : window.event; // for IE
if (e.keyCode==13) return true;
if (!this.ProcessKeys(e)) return false;
if (this.lastKey==38) // Up
{
if (childIndex>0)
{
var newIndex = childIndex-1;
document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
}
else // already at first child, jump to parent
{
document.getElementById('Item'+itemIndex).focus();
}
}
else if (this.lastKey==40) // Down
{
var newIndex = childIndex+1;
var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
if (!elem) // last child, jump to parent next parent
{
elem = this.NavNext(itemIndex+1);
}
if (elem)
{
elem.focus();
}
}
else if (this.lastKey==27) // Escape
{
parent.searchBox.CloseResultsWindow();
parent.document.getElementById("MSearchField").focus();
}
else if (this.lastKey==13) // Enter
{
return true;
}
return false;
}
}
function setKeyActions(elem,action)
{
elem.setAttribute('onkeydown',action);
elem.setAttribute('onkeypress',action);
elem.setAttribute('onkeyup',action);
}
function setClassAttr(elem,attr)
{
elem.setAttribute('class',attr);
elem.setAttribute('className',attr);
}
function createResults()
{
var results = document.getElementById("SRResults");
for (var e=0; e<searchData.length; e++)
{
var id = searchData[e][0];
var srResult = document.createElement('div');
srResult.setAttribute('id','SR_'+id);
setClassAttr(srResult,'SRResult');
var srEntry = document.createElement('div');
setClassAttr(srEntry,'SREntry');
var srLink = document.createElement('a');
srLink.setAttribute('id','Item'+e);
setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
setClassAttr(srLink,'SRSymbol');
srLink.innerHTML = searchData[e][1][0];
srEntry.appendChild(srLink);
if (searchData[e][1].length==2) // single result
{
srLink.setAttribute('href',searchData[e][1][1][0]);
if (searchData[e][1][1][1])
{
srLink.setAttribute('target','_parent');
}
var srScope = document.createElement('span');
setClassAttr(srScope,'SRScope');
srScope.innerHTML = searchData[e][1][1][2];
srEntry.appendChild(srScope);
}
else // multiple results
{
srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
var srChildren = document.createElement('div');
setClassAttr(srChildren,'SRChildren');
for (var c=0; c<searchData[e][1].length-1; c++)
{
var srChild = document.createElement('a');
srChild.setAttribute('id','Item'+e+'_c'+c);
setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
setClassAttr(srChild,'SRScope');
srChild.setAttribute('href',searchData[e][1][c+1][0]);
if (searchData[e][1][c+1][1])
{
srChild.setAttribute('target','_parent');
}
srChild.innerHTML = searchData[e][1][c+1][2];
srChildren.appendChild(srChild);
}
srEntry.appendChild(srChildren);
}
srResult.appendChild(srEntry);
results.appendChild(srResult);
}
}
function init_search()
{
var results = document.getElementById("MSearchSelectWindow");
for (var key in indexSectionLabels)
{
var link = document.createElement('a');
link.setAttribute('class','SelectItem');
link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
link.href='javascript:void(0)';
link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
results.appendChild(link);
}
searchBox.OnSelectItem(0);
}

BIN
html/search/search_l.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

BIN
html/search/search_m.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

BIN
html/search/search_r.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

12
html/search/searchdata.js Normal file
View file

@ -0,0 +1,12 @@
var indexSectionsWithContent =
{
};
var indexSectionNames =
{
};
var indexSectionLabels =
{
};

BIN
html/splitbar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

BIN
html/sync_off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

BIN
html/sync_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

BIN
html/tab_a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

BIN
html/tab_b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
html/tab_h.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

BIN
html/tab_s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

1
html/tabs.css Normal file

File diff suppressed because one or more lines are too long

11
index.html Normal file
View file

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="1;url=html/index.html">
<title>Page Redirection</title>
</head>
<body>
If you are not redirected automatically, follow the <a href="html/index.html">link to the documentation</a>
</body>
</html>

View file

@ -1,23 +0,0 @@
#######################################
# Syntax Coloring Map for CAN library
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
#######################################
# Structures (KEYWORD3)
#######################################
######################################
# Constants (LITERAL1)
#######################################

View file

@ -1,9 +0,0 @@
name=Adafruit CAN
version=0.2.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for native CAN.
paragraph=Arduino library for native CAN.
category=Sensors
url=https://github.com/adafruit/Adafruit_CAN
architectures=samd

View file

@ -1,216 +0,0 @@
// Copyright (c) Sandeep Mistry. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include "CANController.h"
CANControllerClass::CANControllerClass() :
_onReceive(NULL),
_packetBegun(false),
_txId(-1),
_txExtended(-1),
_txRtr(false),
_txDlc(0),
_txLength(0),
_rxId(-1),
_rxExtended(false),
_rxRtr(false),
_rxDlc(0),
_rxLength(0),
_rxIndex(0)
{
// overide Stream timeout value
setTimeout(0);
}
CANControllerClass::~CANControllerClass()
{
}
int CANControllerClass::begin(long /*baudRate*/)
{
_packetBegun = false;
_txId = -1;
_txRtr =false;
_txDlc = 0;
_txLength = 0;
_rxId = -1;
_rxRtr = false;
_rxDlc = 0;
_rxLength = 0;
_rxIndex = 0;
return 1;
}
void CANControllerClass::end()
{
}
int CANControllerClass::beginPacket(int id, int dlc, bool rtr)
{
if (id < 0 || id > 0x7FF) {
return 0;
}
if (dlc > 8) {
return 0;
}
_packetBegun = true;
_txId = id;
_txExtended = false;
_txRtr = rtr;
_txDlc = dlc;
_txLength = 0;
memset(_txData, 0x00, sizeof(_txData));
return 1;
}
int CANControllerClass::beginExtendedPacket(long id, int dlc, bool rtr)
{
if (id < 0 || id > 0x1FFFFFFF) {
return 0;
}
if (dlc > 8) {
return 0;
}
_packetBegun = true;
_txId = id;
_txExtended = true;
_txRtr = rtr;
_txDlc = dlc;
_txLength = 0;
memset(_txData, 0x00, sizeof(_txData));
return 1;
}
int CANControllerClass::endPacket()
{
if (!_packetBegun) {
return 0;
}
_packetBegun = false;
if (_txDlc >= 0) {
_txLength = _txDlc;
}
return 1;
}
int CANControllerClass::parsePacket()
{
return 0;
}
long CANControllerClass::packetId()
{
return _rxId;
}
bool CANControllerClass::packetExtended()
{
return _rxExtended;
}
bool CANControllerClass::packetRtr()
{
return _rxRtr;
}
int CANControllerClass::packetDlc()
{
return _rxDlc;
}
size_t CANControllerClass::write(uint8_t byte)
{
return write(&byte, sizeof(byte));
}
size_t CANControllerClass::write(const uint8_t *buffer, size_t size)
{
if (!_packetBegun) {
return 0;
}
if (size > (sizeof(_txData) - _txLength)) {
size = sizeof(_txData) - _txLength;
}
memcpy(&_txData[_txLength], buffer, size);
_txLength += size;
return size;
}
int CANControllerClass::available()
{
return (_rxLength - _rxIndex);
}
int CANControllerClass::read()
{
if (!available()) {
return -1;
}
return _rxData[_rxIndex++];
}
int CANControllerClass::peek()
{
if (!available()) {
return -1;
}
return _rxData[_rxIndex];
}
void CANControllerClass::flush()
{
}
void CANControllerClass::onReceive(void(*callback)(int))
{
_onReceive = callback;
}
int CANControllerClass::filter(int /*id*/, int /*mask*/)
{
return 0;
}
int CANControllerClass::filterExtended(long /*id*/, long /*mask*/)
{
return 0;
}
int CANControllerClass::observe()
{
return 0;
}
int CANControllerClass::loopback()
{
return 0;
}
int CANControllerClass::sleep()
{
return 0;
}
int CANControllerClass::wakeup()
{
return 0;
}

View file

@ -1,71 +0,0 @@
// Copyright (c) Sandeep Mistry. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#ifndef CAN_CONTROLLER_H
#define CAN_CONTROLLER_H
#include <Arduino.h>
class CANControllerClass : public Stream {
public:
virtual int begin(long baudRate);
virtual void end();
int beginPacket(int id, int dlc = -1, bool rtr = false);
int beginExtendedPacket(long id, int dlc = -1, bool rtr = false);
virtual int endPacket();
virtual int parsePacket();
long packetId();
bool packetExtended();
bool packetRtr();
int packetDlc();
// from Print
virtual size_t write(uint8_t byte);
virtual size_t write(const uint8_t *buffer, size_t size);
// from Stream
virtual int available();
virtual int read();
virtual int peek();
virtual void flush();
virtual void onReceive(void(*callback)(int));
virtual int filter(int id) { return filter(id, 0x7ff); }
virtual int filter(int id, int mask);
virtual int filterExtended(long id) { return filterExtended(id, 0x1fffffff); }
virtual int filterExtended(long id, long mask);
virtual int observe();
virtual int loopback();
virtual int sleep();
virtual int wakeup();
protected:
CANControllerClass();
virtual ~CANControllerClass();
protected:
void (*_onReceive)(int);
bool _packetBegun;
long _txId;
bool _txExtended;
bool _txRtr;
int _txDlc;
int _txLength;
uint8_t _txData[8];
long _rxId;
bool _rxExtended;
bool _rxRtr;
int _rxDlc;
int _rxLength;
int _rxIndex;
uint8_t _rxData[8];
};
#endif

View file

@ -1,567 +0,0 @@
// Copyright 2020 © Jeff Epler for Adafruit Industries. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full
// license information.
#if defined(ADAFRUIT_FEATHER_M4_CAN)
#include <stdint.h>
#include <stdlib.h>
#include "CANSAME5x.h"
#include "wiring_private.h"
#define DEBUG_CAN (0)
#if DEBUG_CAN
#define DEBUG_PRINT(...) (Serial.print(__VA_ARGS__), ((void)0))
#define DEBUG_PRINTLN(...) (Serial.println(__VA_ARGS__), ((void)0))
#else
#define DEBUG_PRINT(...) ((void)0)
#define DEBUG_PRINTLN(...) ((void)0)
#endif
namespace {
#include "CANSAME5x_port.h"
}
#define hw (reinterpret_cast<Can *>(this->_hw))
#define state (reinterpret_cast<_canSAME5x_state *>(this->_state))
#define DIV_ROUND(a, b) (((a) + (b) / 2) / (b))
#define DIV_ROUND_UP(a, b) (((a) + (b)-1) / (b))
#define GCLK_CAN1 GCLK_PCHCTRL_GEN_GCLK1_Val
#define GCLK_CAN0 GCLK_PCHCTRL_GEN_GCLK1_Val
#define ADAFRUIT_ZEROCAN_TX_BUFFER_SIZE (1)
#define ADAFRUIT_ZEROCAN_RX_FILTER_SIZE (1)
#define ADAFRUIT_ZEROCAN_RX_FIFO_SIZE (8)
#define ADAFRUIT_ZEROCAN_MAX_MESSAGE_LENGTH (8)
namespace {
template <class T, std::size_t N>
constexpr size_t size(const T (&array)[N]) noexcept {
return N;
}
// Adapted from ASF3 interrupt_sam_nvic.c:
volatile unsigned long cpu_irq_critical_section_counter = 0;
volatile unsigned char cpu_irq_prev_interrupt_state = 0;
void cpu_irq_enter_critical(void) {
if (!cpu_irq_critical_section_counter) {
if (__get_PRIMASK() == 0) { // IRQ enabled?
__disable_irq(); // Disable it
__DMB();
cpu_irq_prev_interrupt_state = 1;
} else {
// Make sure the to save the prev state as false
cpu_irq_prev_interrupt_state = 0;
}
}
cpu_irq_critical_section_counter++;
}
void cpu_irq_leave_critical(void) {
// Check if the user is trying to leave a critical section
// when not in a critical section
if (cpu_irq_critical_section_counter > 0) {
cpu_irq_critical_section_counter--;
// Only enable global interrupts when the counter
// reaches 0 and the state of the global interrupt flag
// was enabled when entering critical state */
if ((!cpu_irq_critical_section_counter) && cpu_irq_prev_interrupt_state) {
__DMB();
__enable_irq();
}
}
}
// This appears to be a typo (transposition error) in the ASF4 headers
// It's called the "Extended ID Filter Entry"
typedef CanMramXifde CanMramXidfe;
typedef uint32_t can_filter_t;
struct _canSAME5x_tx_buf {
CAN_TXBE_0_Type txb0;
CAN_TXBE_1_Type txb1;
__attribute__((aligned(4))) uint8_t data[8];
};
struct _canSAME5x_rx_fifo {
CAN_RXF0E_0_Type rxf0;
CAN_RXF0E_1_Type rxf1;
__attribute((aligned(4))) uint8_t data[ADAFRUIT_ZEROCAN_MAX_MESSAGE_LENGTH];
} can_rx_fifo_t;
struct _canSAME5x_state {
_canSAME5x_tx_buf tx_buffer[ADAFRUIT_ZEROCAN_TX_BUFFER_SIZE];
_canSAME5x_rx_fifo rx_fifo[ADAFRUIT_ZEROCAN_RX_FIFO_SIZE];
CanMramSidfe standard_rx_filter[ADAFRUIT_ZEROCAN_RX_FILTER_SIZE];
CanMramXifde extended_rx_filter[ADAFRUIT_ZEROCAN_RX_FILTER_SIZE];
};
// This data must be in the first 64kB of RAM. The "canram" section
// receives special support from the linker file in the Feather M4 CAN's
// board support package.
__attribute__((section(".canram"))) _canSAME5x_state can_state[2];
constexpr uint32_t can_frequency = VARIANT_GCLK1_FREQ;
bool compute_nbtp(uint32_t baudrate, CAN_NBTP_Type &result) {
uint32_t clocks_per_bit = DIV_ROUND(can_frequency, baudrate);
uint32_t clocks_to_sample = DIV_ROUND(clocks_per_bit * 7, 8);
uint32_t clocks_after_sample = clocks_per_bit - clocks_to_sample;
uint32_t divisor = max(DIV_ROUND_UP(clocks_to_sample, 256),
DIV_ROUND_UP(clocks_after_sample, 128));
if (divisor > 32) {
return false;
}
result.bit.NTSEG1 = DIV_ROUND(clocks_to_sample, divisor) - 2;
result.bit.NTSEG2 = DIV_ROUND(clocks_after_sample, divisor) - 1;
result.bit.NBRP = divisor - 1;
result.bit.NSJW = DIV_ROUND(clocks_after_sample, divisor * 4);
return true;
}
EPioType find_pin(const can_function *table, size_t n, int arduino_pin,
int &instance) {
if (arduino_pin < 0 || arduino_pin > PINS_COUNT) {
return (EPioType)-1;
}
unsigned port = g_APinDescription[arduino_pin].ulPort;
unsigned pin = g_APinDescription[arduino_pin].ulPin;
for (size_t i = 0; i < n; i++) {
if (table[i].port == port && table[i].pin == pin) {
if (instance == -1 || table[i].instance == instance) {
DEBUG_PRINT("found #");
DEBUG_PRINTLN(i);
instance = table[i].instance;
return EPioType(table[i].mux);
}
}
}
return (EPioType)-1;
}
} // namespace
CANSAME5x::CANSAME5x(uint8_t TX_PIN, uint8_t RX_PIN)
: _tx(TX_PIN), _rx(RX_PIN) {}
#ifdef PIN_CAN_TX
CANSAME5x::CANSAME5x() : _tx(PIN_CAN_TX), _rx(PIN_CAN_RX) {}
#else
CANSAME5x::CANSAME5x() : _tx(-1) {}
#endif
CANSAME5x::~CANSAME5x() {}
int CANSAME5x::begin(long baudrate) {
if (_tx == -1) {
return 0;
}
DEBUG_PRINT("_rx ");
DEBUG_PRINT(_rx);
DEBUG_PRINT(" ulPort=");
DEBUG_PRINT(g_APinDescription[_rx].ulPort);
DEBUG_PRINT(" ulPin=");
DEBUG_PRINTLN(g_APinDescription[_rx].ulPin);
DEBUG_PRINTLN("rx pin table");
for (size_t i = 0; i < size(can_rx); i++) {
DEBUG_PRINT(i);
DEBUG_PRINT(" port=");
DEBUG_PRINT(can_rx[i].port);
DEBUG_PRINT(" pin=");
DEBUG_PRINT(can_rx[i].pin);
DEBUG_PRINT(" instance=");
DEBUG_PRINTLN(can_rx[i].instance);
}
DEBUG_PRINT("_tx ");
DEBUG_PRINT(_tx);
DEBUG_PRINT(" ulPort=");
DEBUG_PRINT(g_APinDescription[_tx].ulPort);
DEBUG_PRINT(" ulPin=");
DEBUG_PRINTLN(g_APinDescription[_tx].ulPin);
DEBUG_PRINTLN("tx pin table");
for (size_t i = 0; i < size(can_tx); i++) {
DEBUG_PRINT(i);
DEBUG_PRINT(" port=");
DEBUG_PRINT(can_tx[i].port);
DEBUG_PRINT(" pin=");
DEBUG_PRINT(can_tx[i].pin);
DEBUG_PRINT(" instance=");
DEBUG_PRINTLN(can_tx[i].instance);
}
int instance = -1;
EPioType tx_function = find_pin(can_tx, size(can_tx), _tx, instance);
EPioType rx_function = find_pin(can_rx, size(can_rx), _rx, instance);
if (tx_function == EPioType(-1) || rx_function == EPioType(-1) ||
instance == -1) {
return 0;
}
CAN_NBTP_Type nbtp;
if (!compute_nbtp(baudrate, nbtp)) {
return 0;
}
_idx = instance;
_hw = reinterpret_cast<void *>(_idx == 0 ? CAN0 : CAN1);
_state = reinterpret_cast<void *>(&can_state[_idx]);
memset(state, 0, sizeof(*state));
pinPeripheral(_tx, tx_function);
pinPeripheral(_rx, rx_function);
if (_idx == 0) {
GCLK->PCHCTRL[CAN0_GCLK_ID].reg = GCLK_CAN0 | (1 << GCLK_PCHCTRL_CHEN_Pos);
} else {
GCLK->PCHCTRL[CAN1_GCLK_ID].reg = GCLK_CAN1 | (1 << GCLK_PCHCTRL_CHEN_Pos);
}
// reset and allow configuration change
hw->CCCR.bit.INIT = 1;
while (!hw->CCCR.bit.INIT) {
}
hw->CCCR.bit.CCE = 1;
// All TX data has an 8 byte payload (max)
{
CAN_TXESC_Type esc = {};
esc.bit.TBDS = CAN_TXESC_TBDS_DATA8_Val;
hw->TXESC.reg = esc.reg;
}
// Set up TX buffer
{
CAN_TXBC_Type bc = {};
bc.bit.TBSA = (uint32_t)state->tx_buffer;
bc.bit.NDTB = ADAFRUIT_ZEROCAN_TX_BUFFER_SIZE;
bc.bit.TFQM = 0; // Messages are transmitted in the order submitted
hw->TXBC.reg = bc.reg;
}
// All RX data has an 8 byte payload (max)
{
CAN_RXESC_Type esc = {};
esc.bit.F0DS = CAN_RXESC_F0DS_DATA8_Val;
esc.bit.F1DS = CAN_RXESC_F1DS_DATA8_Val;
esc.bit.RBDS = CAN_RXESC_RBDS_DATA8_Val;
hw->RXESC.reg = esc.reg;
}
// Set up RX fifo 0
{
CAN_RXF0C_Type rxf = {};
rxf.bit.F0SA = (uint32_t)state->rx_fifo;
rxf.bit.F0S = ADAFRUIT_ZEROCAN_RX_FIFO_SIZE;
hw->RXF0C.reg = rxf.reg;
}
// Reject all packets not explicitly requested
{
CAN_GFC_Type gfc = {};
gfc.bit.RRFE = 0;
gfc.bit.ANFS = CAN_GFC_ANFS_REJECT_Val;
gfc.bit.ANFE = CAN_GFC_ANFE_REJECT_Val;
hw->GFC.reg = gfc.reg;
}
// Initially, receive all standard and extended packets to FIFO 0
state->standard_rx_filter[0].SIDFE_0.bit.SFID1 = 0; // ID
state->standard_rx_filter[0].SIDFE_0.bit.SFID2 = 0; // mask
state->standard_rx_filter[0].SIDFE_0.bit.SFEC = CAN_SIDFE_0_SFEC_STF0M_Val;
state->standard_rx_filter[0].SIDFE_0.bit.SFT = CAN_SIDFE_0_SFT_CLASSIC_Val;
state->extended_rx_filter[0].XIDFE_0.bit.EFID1 = 0; // ID
state->extended_rx_filter[0].XIDFE_0.bit.EFEC = CAN_XIDFE_0_EFEC_STF0M_Val;
state->extended_rx_filter[0].XIDFE_1.bit.EFID2 = 0; // mask
state->extended_rx_filter[0].XIDFE_1.bit.EFT = CAN_XIDFE_1_EFT_CLASSIC_Val;
// Set up standard RX filters
{
CAN_SIDFC_Type dfc = {};
dfc.bit.LSS = ADAFRUIT_ZEROCAN_RX_FILTER_SIZE;
dfc.bit.FLSSA = (uint32_t)state->standard_rx_filter;
hw->SIDFC.reg = dfc.reg;
}
// Set up extended RX filters
{
CAN_XIDFC_Type dfc = {};
dfc.bit.LSE = ADAFRUIT_ZEROCAN_RX_FILTER_SIZE;
dfc.bit.FLESA = (uint32_t)state->extended_rx_filter;
hw->XIDFC.reg = dfc.reg;
}
// Enable receive IRQ (masked until enabled in NVIC)
hw->IE.bit.RF0NE = true;
if (_idx == 0) {
hw->ILE.bit.EINT0 = true;
} else {
hw->ILE.bit.EINT1 = true;
}
hw->ILS.bit.RF0NL = _idx;
// Set nominal baud rate
hw->NBTP.reg = nbtp.reg;
// hardware is ready for use
hw->CCCR.bit.CCE = 0;
hw->CCCR.bit.INIT = 0;
while (hw->CCCR.bit.INIT) {
}
instances[_idx] = this;
return 1;
}
void CANSAME5x::end() {
instances[_idx] = 0;
pinMode(_tx, INPUT);
pinMode(_rx, INPUT);
// reset and disable clock
hw->CCCR.bit.INIT = 1;
while (!hw->CCCR.bit.INIT) {
}
if (_idx == 0) {
GCLK->PCHCTRL[CAN0_GCLK_ID].reg = 0;
} else {
GCLK->PCHCTRL[CAN1_GCLK_ID].reg = 0;
}
}
int CANSAME5x::endPacket() {
if (!CANControllerClass::endPacket()) {
return 0;
}
bus_autorecover();
// TODO wait for TX buffer to free
_canSAME5x_tx_buf &buf = state->tx_buffer[0];
buf.txb0.bit.ESI = false;
buf.txb0.bit.XTD = _txExtended;
buf.txb0.bit.RTR = _txRtr;
if (_txExtended) {
buf.txb0.bit.ID = _txId;
} else {
buf.txb0.bit.ID = _txId << 18;
}
buf.txb1.bit.MM = 0;
buf.txb1.bit.EFC = 0;
buf.txb1.bit.FDF = 0;
buf.txb1.bit.BRS = 0;
buf.txb1.bit.DLC = _txLength;
if (!_txRtr) {
memcpy(buf.data, _txData, _txLength);
}
// TX buffer add request
hw->TXBAR.reg = 1;
// wait 8ms (hard coded for now) for TX to occur
for (int i = 0; i < 8000; i++) {
if (hw->TXBTO.reg & 1) {
return true;
}
yield();
}
return 1;
}
int CANSAME5x::_parsePacket() {
if (!hw->RXF0S.bit.F0FL) {
return 0;
}
int index = hw->RXF0S.bit.F0GI;
auto &hw_message = state->rx_fifo[index];
_rxExtended = hw_message.rxf0.bit.XTD;
_rxRtr = hw_message.rxf0.bit.RTR;
_rxDlc = hw_message.rxf1.bit.DLC;
if (_rxExtended) {
_rxId = hw_message.rxf0.bit.ID;
} else {
_rxId = hw_message.rxf0.bit.ID >> 18;
}
if (_rxRtr) {
_rxLength = 0;
} else {
_rxLength = _rxDlc;
memcpy(_rxData, hw_message.data, _rxLength);
}
_rxIndex = 0;
hw->RXF0A.bit.F0AI = index;
return _rxDlc;
}
int CANSAME5x::parsePacket() {
cpu_irq_enter_critical();
bus_autorecover();
int result = _parsePacket();
cpu_irq_leave_critical();
return result;
}
void CANSAME5x::onReceive(void (*callback)(int)) {
CANControllerClass::onReceive(callback);
auto irq = _idx == 0 ? CAN0_IRQn : CAN1_IRQn;
if (callback) {
NVIC_EnableIRQ(irq);
} else {
NVIC_DisableIRQ(irq);
}
}
void CANSAME5x::handleInterrupt() {
uint32_t ir = hw->IR.reg;
if (ir & CAN_IR_RF0N) {
while (int i = parsePacket())
_onReceive(i);
}
hw->IR.reg = ir;
}
int CANSAME5x::filter(int id, int mask) {
// accept matching standard messages
state->standard_rx_filter[0].SIDFE_0.bit.SFID1 = id;
state->standard_rx_filter[0].SIDFE_0.bit.SFID2 = mask;
state->standard_rx_filter[0].SIDFE_0.bit.SFEC = CAN_SIDFE_0_SFEC_STF0M_Val;
state->standard_rx_filter[0].SIDFE_0.bit.SFT = CAN_SIDFE_0_SFT_CLASSIC_Val;
// reject all extended messages
state->extended_rx_filter[0].XIDFE_0.bit.EFID1 = 0; // ID
state->extended_rx_filter[0].XIDFE_0.bit.EFEC = CAN_XIDFE_0_EFEC_REJECT_Val;
state->extended_rx_filter[0].XIDFE_1.bit.EFID2 = 0; // mask
state->extended_rx_filter[0].XIDFE_1.bit.EFT = CAN_XIDFE_1_EFT_CLASSIC_Val;
return 1;
}
int CANSAME5x::filterExtended(long id, long mask) {
// reject all standard messages
state->standard_rx_filter[0].SIDFE_0.bit.SFID1 = 0;
state->standard_rx_filter[0].SIDFE_0.bit.SFID2 = 0;
state->standard_rx_filter[0].SIDFE_0.bit.SFEC = CAN_SIDFE_0_SFEC_REJECT_Val;
state->standard_rx_filter[0].SIDFE_0.bit.SFT = CAN_SIDFE_0_SFT_CLASSIC_Val;
// accept matching extended messages
state->extended_rx_filter[0].XIDFE_0.bit.EFID1 = id;
state->extended_rx_filter[0].XIDFE_0.bit.EFEC = CAN_XIDFE_0_EFEC_STF0M_Val;
state->extended_rx_filter[0].XIDFE_1.bit.EFID2 = mask;
state->extended_rx_filter[0].XIDFE_1.bit.EFT = CAN_XIDFE_1_EFT_CLASSIC_Val;
return 1;
}
int CANSAME5x::observe() {
hw->CCCR.bit.INIT = 1;
while (!hw->CCCR.bit.INIT) {
}
hw->CCCR.bit.CCE = 1;
hw->CCCR.bit.MON = 1;
hw->CCCR.bit.CCE = 0;
hw->CCCR.bit.INIT = 0;
while (hw->CCCR.bit.INIT) {
}
return 1;
}
int CANSAME5x::loopback() {
hw->CCCR.bit.INIT = 1;
while (!hw->CCCR.bit.INIT) {
}
hw->CCCR.bit.CCE = 1;
hw->CCCR.bit.TEST = 1;
hw->TEST.bit.LBCK = 1;
hw->CCCR.bit.CCE = 0;
hw->CCCR.bit.INIT = 0;
while (hw->CCCR.bit.INIT) {
}
return 1;
}
int CANSAME5x::sleep() {
hw->CCCR.bit.CSR = 1;
while (!hw->CCCR.bit.CSA) {
}
if (_idx == 0) {
GCLK->PCHCTRL[CAN0_GCLK_ID].reg = 0;
} else {
GCLK->PCHCTRL[CAN1_GCLK_ID].reg = 0;
}
return 1;
}
int CANSAME5x::wakeup() {
if (_idx == 0) {
GCLK->PCHCTRL[CAN0_GCLK_ID].reg = GCLK_CAN0 | (1 << GCLK_PCHCTRL_CHEN_Pos);
} else {
GCLK->PCHCTRL[CAN1_GCLK_ID].reg = GCLK_CAN1 | (1 << GCLK_PCHCTRL_CHEN_Pos);
}
hw->CCCR.bit.INIT = 0;
while (hw->CCCR.bit.INIT) {
}
return 1;
}
void CANSAME5x::bus_autorecover() {
if (hw->PSR.bit.BO) {
DEBUG_PRINTLN("bus autorecovery activated");
hw->CCCR.bit.INIT = 0;
while (hw->CCCR.bit.INIT) {
}
}
}
void CANSAME5x::onInterrupt() {
for (int i = 0; i < size(instances); i++) {
CANSAME5x *instance = instances[i];
if (instance) {
instance->handleInterrupt();
}
}
}
extern "C" __attribute__((externally_visible)) void CAN0_Handler() {
cpu_irq_enter_critical();
CANSAME5x::onInterrupt();
cpu_irq_leave_critical();
}
extern "C" __attribute__((externally_visible)) void CAN1_Handler() {
cpu_irq_enter_critical();
CANSAME5x::onInterrupt();
cpu_irq_leave_critical();
}
CANSAME5x *CANSAME5x::instances[2];
#endif

View file

@ -1,53 +0,0 @@
// Copyright 2020 © Jeff Epler for Adafruit Industries. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full
// license information.
#include "CANController.h"
class CANSAME5x : public CANControllerClass {
public:
CANSAME5x();
CANSAME5x(uint8_t tx_pin, uint8_t rx_pin);
~CANSAME5x() final;
int begin(long baudRate) final;
void end() final;
int endPacket() final;
int parsePacket() final;
void onReceive(void (*callback)(int)) final;
using CANControllerClass::filter;
int filter(int id, int mask) final;
using CANControllerClass::filterExtended;
int filterExtended(long id, long mask) final;
int observe() final;
int loopback() final;
int sleep() final;
int wakeup() final;
// void dumpRegisters(Stream &out);
private:
void bus_autorecover();
void handleInterrupt();
int _parsePacket();
private:
int8_t _tx, _rx;
int8_t _idx;
// intr_handle_t _intrHandle;
void *_state;
void *_hw;
static CANSAME5x *instances[2];
static void onInterrupt();
friend void CAN0_Handler(void);
friend void CAN1_Handler(void);
};

File diff suppressed because it is too large Load diff