|
SGCoreCs
v1.3.1
SenseGlove C# API
|
A sequence which collects data points untill specific criteria have been met. It must be 'fed' an Update command from your program in order to work. More...
Public Member Functions | |
| HG_CalibrationSequence (SGCore.HapticGlove gloveToCalibrate) | |
| Create a new instance of a base HapitcGlove Calibration Sequence. More... | |
| virtual void | Reset () |
| Resets this calibration sequence's data, but not it's LinkedGlove. More... | |
| virtual void | AddDataPoint (Vect3D[] calibrationData) |
| Safely adds calibration data. Automatically done within 'Update' More... | |
| virtual void | Update (float deltaTime_s) |
| Update this calibration sequence with new data. We use deltaTime to check for things like stability. More... | |
| virtual void | ConfirmCurrentStep () |
| Manual confirmation of whatever step we're supposed to making at the moment. More... | |
| virtual bool | CompileRange (out SensorRange range) |
| Compile a min/max range from the datapoints collected by this sequence. Returns true if it's actually possible. More... | |
| virtual bool | CompileProfile (SGCore.DeviceType forDevice, bool rightHand, out SGCore.HandProfile profile) |
| Compile a profile from the datapoints collected by this sequence. Returns true if it's actually possible. More... | |
| bool | GetHandPose (out SGCore.HandPose currentPose) |
| Returns the current HandPose; either the one we should be making, or what it would look like at the moment. More... | |
| virtual bool | GetHandPose (bool rightHand, out SGCore.HandPose currentPose) |
| Returns the current HandPose; either the one we should be making, or what it would look like at the moment. More... | |
| virtual bool | GetHandPose (SGCore.Kinematics.BasicHandModel handDimensions, out SGCore.HandPose currentPose) |
| Retrieve a handPose based on set hand dimensions. More... | |
| virtual string | GetCurrentInstuction (string nextStepKey="") |
| Retrieve instructions on what to do during the current step. More... | |
| virtual string | GetDebugInfo () |
| Retrieve debug information from the sequence More... | |
Static Public Member Functions | |
| static bool | CompileProfile (SensorRange range, SGCore.DeviceType forDevice, bool rightHand, out SGCore.HandProfile profile) |
| Converts a calibration range taken from a Calibration sequence, and converts it into a profile. Use this if you're not actually using the sequence. More... | |
Public Attributes | |
| List< CalDataPoint > | calibrationPoints = new List<CalDataPoint>() |
| Calibration points colledted during this calibration process. One is added every thme the "Update()" function is called. Used to create a profile after the calibration finishes. More... | |
| float | elapsedTime = 0 |
| How much time has elapsed during this calibration sequence. Useful for logging or for automated functions. More... | |
Static Public Attributes | |
| const int | maxDataPoints = 60000 |
| The maximum buffer size for calibration points. Once calibrationPoints exceeds this value, the More... | |
Protected Member Functions | |
| HG_CalibrationSequence () | |
| Basic constructor for subclasses to inherit from More... | |
Protected Attributes | |
| SGCore.HapticGlove | iGlove |
| Glove linked to this calibration sequence. Will attempt to gram data from this glove evey time Update() is called. More... | |
Properties | |
| bool | ManualCompleted [get, set] |
| Used to determine if the user has manually ended the sequence, to prevent us from adding any more calibration points. More... | |
| SGCore.Kinematics.BasicHandModel | HandModel [get, set] |
| Kinematic information to generate a calibration preview pose. More... | |
| virtual int | CurrentStageInt [get] |
| If a sequence consists of multiple stages, this integer will show you which one is currently active. More... | |
| SGCore.HapticGlove | LinkedGlove [get, set] |
| The Glove linked to this Calibration Sequence. Can be changed or re-assigned. More... | |
| int | DataPointCount [get] |
| Returns the amount of calibration points collected so far More... | |
| virtual bool | AutoCompleted [get] |
| Whether or not this sequence was completed as per it's own rules More... | |
| virtual bool | Completed [get] |
| Returns true if this sequence is marked as 'complete' and can begin compiling a profile. More... | |
A sequence which collects data points untill specific criteria have been met. It must be 'fed' an Update command from your program in order to work.
|
protected |
Basic constructor for subclasses to inherit from
| SGCore.Calibration.HG_CalibrationSequence.HG_CalibrationSequence | ( | SGCore.HapticGlove | gloveToCalibrate | ) |
Create a new instance of a base HapitcGlove Calibration Sequence.
| gloveToCalibrate |
|
virtual |
Safely adds calibration data. Automatically done within 'Update'
| calibrationData |
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
|
static |
Converts a calibration range taken from a Calibration sequence, and converts it into a profile. Use this if you're not actually using the sequence.
| range | |
| forDevice | |
| rightHand | |
| profile |
|
virtual |
Compile a profile from the datapoints collected by this sequence. Returns true if it's actually possible.
| forDevice | |
| rightHand | |
| profile |
|
virtual |
Compile a min/max range from the datapoints collected by this sequence. Returns true if it's actually possible.
| range |
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
|
virtual |
Manual confirmation of whatever step we're supposed to making at the moment.
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
|
virtual |
Retrieve instructions on what to do during the current step.
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
|
virtual |
Retrieve debug information from the sequence
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
|
virtual |
Returns the current HandPose; either the one we should be making, or what it would look like at the moment.
| rightHand | |
| currentPose |
| bool SGCore.Calibration.HG_CalibrationSequence.GetHandPose | ( | out SGCore.HandPose | currentPose | ) |
Returns the current HandPose; either the one we should be making, or what it would look like at the moment.
| currentPose |
|
virtual |
Retrieve a handPose based on set hand dimensions.
| handDimensions | |
| currentPose |
|
virtual |
Resets this calibration sequence's data, but not it's LinkedGlove.
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
|
virtual |
Update this calibration sequence with new data. We use deltaTime to check for things like stability.
| deltaTime_s |
Reimplemented in SGCore.Calibration.HG_QuickCalibration.
| List<CalDataPoint> SGCore.Calibration.HG_CalibrationSequence.calibrationPoints = new List<CalDataPoint>() |
Calibration points colledted during this calibration process. One is added every thme the "Update()" function is called. Used to create a profile after the calibration finishes.
| float SGCore.Calibration.HG_CalibrationSequence.elapsedTime = 0 |
How much time has elapsed during this calibration sequence. Useful for logging or for automated functions.
|
protected |
Glove linked to this calibration sequence. Will attempt to gram data from this glove evey time Update() is called.
|
static |
The maximum buffer size for calibration points. Once calibrationPoints exceeds this value, the
|
get |
Whether or not this sequence was completed as per it's own rules
|
get |
Returns true if this sequence is marked as 'complete' and can begin compiling a profile.
|
get |
If a sequence consists of multiple stages, this integer will show you which one is currently active.
|
get |
Returns the amount of calibration points collected so far
|
getset |
Kinematic information to generate a calibration preview pose.
|
getset |
The Glove linked to this Calibration Sequence. Can be changed or re-assigned.
|
getset |
Used to determine if the user has manually ended the sequence, to prevent us from adding any more calibration points.


Let’s begin by examining the AddHealth
dataset
qacdata::addhealth
#> # A tibble: 5,114 x 979
#> RACE ETHNICITY h4od1y iyear4 AID BIO_SEX agew1 IMONTH4 IDAY4 MACNO4
#> <dbl> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 2 0 1976 2008 5710~ 2 19.4 5 6 2.29e6
#> 2 5 0 1976 2008 5710~ 1 20.4 5 22 2.29e6
#> 3 2 0 1981 2008 5710~ 1 15.2 11 2 2.29e6
#> 4 2 0 1981 2008 5711~ 1 14.9 6 29 2.29e6
#> 5 2 0 1979 2008 5711~ 1 17.3 11 11 2.29e6
#> 6 5 0 1979 2008 5711~ 1 NA 3 6 2.29e6
#> 7 2 0 1982 2008 5711~ 2 13.7 5 9 2.29e6
#> 8 5 0 1982 2008 5712~ 2 14.3 6 12 2.29e6
#> 9 1 1 1979 2008 5713~ 1 17.5 6 21 2.29e6
#> 10 3 0 1978 2008 5714~ 1 17.9 4 20 2.29e6
#> # ... with 5,104 more rows, and 969 more variables: INTID4 <dbl>,
#> # BIO_SEX4 <dbl>, VERSION4 <chr>, BREAK_Q <chr>, PRYEAR4 <dbl>,
#> # PRETEST4 <dbl>, PRISON4 <dbl>, H4OD1M <dbl>, H4OD2A <dbl>,
#> # H4OD2B <dbl>, H4OD2C <dbl>, H4OD2D <dbl>, H4OD2E <dbl>, H4OD2F <dbl>,
#> # H4OD3 <dbl>, H4OD4 <dbl>, H4OD5 <dbl>, H4OD6M <dbl>, H4OD6Y <dbl>,
#> # H4OD7 <dbl>, H4WP1 <dbl>, H4WP2M <dbl>, H4WP2Y <dbl>, H4WP3 <dbl>,
#> # H4WP4 <dbl>, H4WP5 <dbl>, H4WP6 <dbl>, H4WP7 <dbl>, H4WP8M <dbl>,
#> # H4WP8Y <dbl>, H4WP9 <dbl>, H4WP10 <dbl>, H4WP11 <dbl>, H4WP12 <dbl>,
#> # H4WP13 <dbl>, H4WP14 <dbl>, H4WP15M <dbl>, H4WP15Y <dbl>,
#> # H4WP16 <dbl>, H4WP17 <dbl>, H4WP18 <dbl>, H4WP19 <dbl>, H4WP20 <dbl>,
#> # H4WP21 <dbl>, H4WP22 <dbl>, H4WP23 <dbl>, H4WP24 <dbl>, H4WP25 <dbl>,
#> # H4WP26 <dbl>, H4WP27 <dbl>, H4WP28 <dbl>, H4WP29M <dbl>,
#> # H4WP29Y <dbl>, H4WP30 <dbl>, H4WP31 <dbl>, H4WP32 <dbl>, H4WP33 <dbl>,
#> # H4WP34 <dbl>, H4WP35 <dbl>, H4WP36 <dbl>, H4WP37 <dbl>, H4WP38 <dbl>,
#> # H4WP39 <dbl>, H4WP40 <dbl>, H4WS1 <dbl>, H4WS2 <dbl>, H4WS3A <dbl>,
#> # H4WS3B <dbl>, H4WS3C <dbl>, H4WS3D <dbl>, H4WS3E <dbl>, H4WS3F <dbl>,
#> # H4WS3G <dbl>, H4WS3H <dbl>, H4WS4 <dbl>, H4WS5 <dbl>, H4GH1 <dbl>,
#> # H4GH2 <dbl>, H4GH3M <dbl>, H4GH3D <dbl>, H4GH3Y <dbl>, H4GH4A <dbl>,
#> # H4GH4B <dbl>, H4GH5F <dbl>, H4GH5I <dbl>, H4GH6 <dbl>, H4GH7 <dbl>,
#> # H4GH8 <dbl>, H4GH9 <dbl>, H4GH10 <dbl>, H4GH11H <dbl>, H4GH11M <dbl>,
#> # H4GH11T <dbl>, H4GH12 <dbl>, H4GH13H <dbl>, H4GH13M <dbl>,
#> # H4GH13T <dbl>, H4HS1 <dbl>, H4HS2A <dbl>, H4HS2B <dbl>, ...
There are 979 columns/variables in this dataset. Normally, we would find variables of interesting by finding the codebook online or accessing a PDF version and hitting Ctrl + F. With the qacdata
packing this search can be done in R
data_search("birth", "AddHealth")
#> # A tibble: 45 x 4
#> dataset col_id description notes
#> <chr> <chr> <chr> <list>
#> 1 AddHealth H4OD1M Respondent's date of birth <tibble [1~
#> 2 AddHealth H4OD1Y Respondent's date of birth <tibble [1~
#> 3 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> 4 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> 5 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> 6 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> 7 AddHealth H4SE2~ "In the past 12 months, did you or your pa~ <tibble [6~
#> 8 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> 9 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> 10 AddHealth H4SE2~ In the past 12 months, did you or your par~ <tibble [6~
#> # ... with 35 more rows
We find 45 possible variables within the AddHealth
dataset that’s description contains the word “birth”. H4TR10
by its description is on “How many live births resulted from (this pregnancy/these pregnancies)?”.
If there are more variables that can we viewed on your console, evoke the View
function.
“H4SE27” seems interesting. Let’s find more about it
data_search("sex", "AddHealth") %>%
get_description("H4SE27")
#> [1] "In the past 12 months, did you have sex with more than one partner at around the same time?"
Lets grab both columns and work with them.
First let’s download the data
data_download("AddHealth", "H4TR10")
#> # A tibble: 5,114 x 1
#> H4TR10
#> <dbl>
#> 1 4
#> 2 97
#> 3 97
#> 4 97
#> 5 1
#> 6 1
#> 7 3
#> 8 1
#> 9 2
#> 10 2
#> # ... with 5,104 more rows
Let’s recode missing values based on the information we got from the get_note
function
data_search("birth", "AddHealth") %>%
get_note("H4TR10")
#> # A tibble: 13 x 4
#> response_value response_label frequency percent
#> <int> <chr> <int> <dbl>
#> 1 0 0 live births 1544 9.83
#> 2 1 1 live birth 3355 21.4
#> 3 11 11 live births 3 0.02
#> 4 2 2 live births 2887 18.4
#> 5 3 3 live births 1240 7.9
#> 6 4 4 live births 362 2.31
#> 7 5 5 live births 97 0.62
#> 8 6 6 live births 23 0.15
#> 9 7 7 live births 10 0.06
#> 10 8 8 live births 1 0.01
#> 11 96 refused 1 0.01
#> 12 97 legitimate skip 6174 39.3
#> 13 98 don't know 4 0.03
data_search("sex", "AddHealth") %>%
get_note("H4SE27")
#> # A tibble: 6 x 4
#> response_value response_label frequency percent
#> <chr> <chr> <int> <dbl>
#> 1 . missing 24 0.15
#> 2 0 no 11300 72.0
#> 3 1 yes 2110 13.4
#> 4 6 refused 9 0.06
#> 5 7 legitimate skip 2256 14.4
#> 6 8 don't know 2 0.01
cleaned_df <- data_download("AddHealth", "H4TR10", "H4SE27") %>%
transmute(births = ifelse(H4TR10 >= 96, NA, H4TR10),
sex = ifelse(H4SE27 >= 8, NA, H4SE27))
cleaned_df
#> # A tibble: 5,114 x 2
#> births sex
#> <dbl> <dbl>
#> 1 4 0
#> 2 NA 7
#> 3 NA 0
#> 4 NA 1
#> 5 1 0
#> 6 1 0
#> 7 3 0
#> 8 1 0
#> 9 2 0
#> 10 2 0
#> # ... with 5,104 more rows
Now we are ready to visualize
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 3.6.1
theme_set(theme_light())
cleaned_df %>%
na.omit() %>%
count(births, sex) %>%
ggplot(aes(x = births, y = n, fill = factor(sex))) +
geom_col() +
labs(title = "Nonsense graph for illustration purposes",
x = "Category of live birthds",
y = "Count",
fill = "Sex Freq")


Phase 1: Before Development Begins
Phase 1.1: Define a SDLC
Before application development starts an adequate SDLC must be defined where security is inherent at each stage.
Phase 1.2: Review Policies and Standards
Ensure that there are appropriate policies, standards, and documen-tation in place. Documentation is extremely important as it gives de-velopment teams guidelines and policies that they can follow.
People can only do the right thing if they know what the right thing is.
If the application is to be developed in Java, it is essential that there is a Java secure coding standard. If the application is to use cryptog-raphy, it is essential that there is a cryptography standard. No pol-icies or standards can cover every situation that the development team will face. By documenting the common and predictable issues, there will be fewer decisions that need to be made during the de-velopment process.
Phase 1.3: Develop Measurement and Metrics Criteria and Ensure Traceability
Before development begins, plan the measurement program. By defining criteria that need to be measured, it provides visibility into defects in both the process and product. It is essential to define the metrics before development begins, as there may be a need to modify the process in order to capture the data.


Restrictions on alcohol advertising come into effect today
by By Digital Desk staffNew laws clamping down on alcohol advertisements come into effect from today.
The measures include a ban on outdoor alcohol ads, such as on public transport and around schools and playgrounds.
Alcohol adverts on children's clothing and in cinemas for films suitable for under 18s will also be banned.
“Studies report consistently that exposure to alcohol advertising is associated with an increased likelihood that children will start to drink or will drink greater quantities if they already do," said Minister for Health, Simon Harris.
"These measures aim to change that situation in Ireland and to remove alcohol advertising from the day-to-day lives of our children.”
“I am determined to continue this fight. These and other measures in the Public Health (Alcohol) Act will effect practical changes in our society in order to ensure that there will be no room for alcohol and alcohol advertising in Irish childhoods."
READ MORE
Tests at Kildare plant may see boil water notice may be lifted today


Survey Questions:
ABOUT YOU
Name (Required)
Link to Photo Image (Required)
Question 1
List your priorities, in order of importance:
Question 2
What kind of a reader are you?
Question 3
How do you spend your free time?
Question 4
Choose a vacation:
Question 5
Describe yourself in traffic:
Question 6
Do you want a hug?
Question 7
Where do you live?
Question 8
Choose a Film:
Question 9
What kind of person are you attracted to?
Question 10
How do you give back to the community?
Question 11
How important is fashion in your life?
Question 12
How clean is your place?


Business, Industry, and Trade
-
- Value added of Non-Financial Business Economy
-
£936.3 bn1st Quarter 2014
-
- UK Gross Expenditure on Research and Development
-
£27 bn2012


Home
Illness Information
Resources
Find a Doctor
Find a Hospital
General Health
Illness Information
STD's
Respiratory Issues
Cardiac Issues
Digestive Health
Menstruation


Security in the cities and urban area is a concern.
Usually you can judge how much crime there is in a certain area by the amount the houses and businesses protect themselves with fences, barbed wire, guard dogs, security guards and electronic alarm systems.
Do not walk anywhere at night, and even during the day, it is advisable do so in groups if possible.
See the U.K. FCO website for the latest security advice.
Keep to main roads and avoid driving at night when visiting Northern KwaZulu Natal and Zululand, as there have been incidents of hi-jacking and robbery, particularly on isolated secondary roads.
Be vigilant on the approach roads to and from Kruger Park where there have been cases of car hijacking.
Avoid isolated beaches and picnic spots. Don’t walk alone, especially in remote areas. Hikers should stick to popular trails. There have been violent attacks on hikers and tourists on Table Mountain.
Last updated March 2016.
The climate varies greatly between the coastal regions and inland, and also between the Atlantic and Indian Ocean coasts. Generally, it can be described as temperate in the Cape area and tropical in the rest of the country. The prevailing winds of summer are SE, replaced in winter by W or NW winds. Gales are frequent and in summer depressions come up from the Southern Ocean accompanied by cold gale force winds. Conditions are particularly bad when such gales blow against the SW flowing Agulhas current.
For those who are concerned about the difficult passage from Durban to Cape Town, advice on the best tactics to use in these stormy waters can be obtained from the Durban Sailing Academy. Daily synoptic charts for the region can be found at http://www.cruisingconnections.co.za/index.php/weather
For Cape Town Weather forecasts phone<PHONE_NUMBER>. Local forecasts are transmitted on VHF Channel 25 at 1015, 1333, 1815 (all times UT) (Monitor Channel 16 and be prepared to wait until radio traffic on other channels has ceased).
Cape Town Radio (SSB) on 4375 8740 13146Mhz USB at 1015 1330 1815 utc daily for forecasts and reports. Gives you barometer pressure and wind speed around the entire SA coast line.
See Communications for details of SSB Nets which also have weather information.
SA Weather and Disaster Observation Service
Free weather service using voluntary weather observers to obtain critical weather information.
For links to free global weather information, forecast services and extreme weather information see the Noonsite Weather Page.
Cape Town (Table Bay) * , Durban * , East London * , Hout Bay , Knysna , Mossel Bay , Port Alfred , Port Elizabeth * , Richards Bay * , Saldanha Bay , Simon's Town , St Helna Bay & Port Owen , St. Francis Bay
* indicates port of entry


Text and copy are never just words, they're important. When designing anything, the content is the thing that gives the design purpose and direction. To communicate both our messages and values, we use the Fira Sans and Clear Sans as our two primary font families. Clear sans 14px
abcdefghijklmnopqrstuvwxyz
0123456789!@#$%^&*()


Metapopulation dynamics A predator requires a prey to colonize a patch A predator requires a prey to persist in a patch
Holt, R.D. (1996). Food webs in space: an island biogeographic perspective. In: Food Webs: Contemporary Perspectives, Polis & Winemiller.
First trophic level : $\frac{dp_1}{dt} = c_1p_1(1-p_1) - e_1p_1$ Which yields : $p_1^* = 1 - e_1/c_1$
Second trophic level : $\frac{dp_2}{dt} = c_2p_2(p_1-p_2) - e_2p_2$ Which yields : $p_2^* = p_1 - e_2/c_2$
Assumptions : A species can only invade an island if it as at least one prey present on the island A species that loses its last prey on the island goes extinct $\frac{dp_g}{dt} = c(1-p_g)q_g - (e + \epsilon_g)p_g$ Where : \(q_g\) : probability that a species has a prey present on the island \(\epsilon_g\): rate a predator loses its last prey on the island
Finer aspects of network structure : Massol et al. 2017. Advances in Ecological Research Addition of allometric constraints : Jacquet et al. 2017. Ecology Letters Other types of interactions : Cazelles et al. 2015. Ecography Co-occurrence and network structure : Cazelles et al. 2016. Theoretical Ecology Metacommunity dimensions : Gravel & Massol. 2019 in Theoretical Ecology.
We want to couple bicknell's thrush with forest dynamics The best would be to have a colonization/extinction model for birds Make colonization conditional on forest type Run the two models simultaneously We would obtain something like : $p_{bicknell}^* = p_{conifers} - e_{bicknell}c_{bicknell}$
Without dynamical data for birds We will derive \(p_{bicknell}^*\) directly from the data with a SDM Couple models sequentially : Evaluate the SDM Run the forest simulation model Predict with the SDM the expected bird distribution using future climate & future forest composition as predictors Repeat the whole procedure for all bird species


| create_pretty {fresh} | R Documentation |
This allow you to change colors of prettyCheckbox
,
prettyRadioButtons
create_pretty( output_file, default = NULL, primary = NULL, success = NULL, info = NULL, warning = NULL, danger = NULL )
output_file |
Specifies path to output file for compiled CSS. |
default |
Default color. |
primary |
Primary color. |
success |
Success color. |
info |
Info color. |
warning |
Warning color. |
danger |
Danger color. |
If output_file = NULL
, the function returns a string value of the compiled CSS.
If the output path is specified, the compiled CSS is written to that file and invisible()
is returned.
# Temporary file tmp <- file.path(tempdir(), "my-pretty.css") # Create the new theme create_pretty( output_file = tmp, primary = "#FFFF00" ) # Clean unlink(tmp)


| TEP: | 131 |
|---|---|
| Group: | TinyOS 8051 Working Group |
| Type: | Informational |
| Status: | Draft |
| TinyOS-Version: | 2.x |
| Author: | Martin Leopold |
| Draft-Created: | 6-Nov-2007 |
| Draft-Version: | 1 |
| Draft-Modified: | 6-Nov-2007 |
| Draft-Discuss: | TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu> |
Note
This memo is informational. It will hopefully be a basis for discussions and suggestions for improvements. Distribution of this memo is unlimited. This memo is in full compliance with TEP 1.
The purpose of this TEP is to provide on overview of how to build a new TinyOS 2 platform. While the purpose of most TEPs is to describe TinyOS 2 entities, we will present concrete suggestions on how to implement a new TinyOS 2 platform. We will use examples and briefly cover the relevant TEPs to present a platform that adheres to the current TinyOS standards. We will not cover the TEPs in detail, but to the full text of each TEP for further information.
This TEP will go through the tool chain setup and the most basic components for a functional TinyOS platform. We consider only TinyOS version 2.x (from now on TinyOS).
Before venturing on this quest we will take a diversion and introduce general TinyOS 2 concepts and terminology (Section 1), readers familiar to TinyOS 2 can skip this section. This document will introduce the TinyOS 2 platform (Section 2) and describes the 3 elements that make up a platform: the tool chain (Section 3) the platform definitions (Section 4) and the chips definitions (Section 5).
Before describing the process of writing TinyOS platforms we will briefly sum up the TinyOS ecosystem and the terminology required in this TEP. To learn more visit the TinyOS website http://www.tinyos.net.
A systems overview is depicted below. In this TEP we will primarily concern our selves with the platform portion of figure and briefly cover the tool chain. This involves writing the necessary drivers and writing rules to pass the code to the TinyOS tool chain. We will not cover sensor boards in this TEP refer to, see [TEP109] for details.
+------------------------------------------+ | Application | +------------------------------------------+ +--------+ +----------+ +--------------+ | TinyOS | + | Platform | + | Sensor board | +--------+ +----------+ +--------------+ | V +-------------------+ | TinyOS tool chain | +-------------------+ | Target platform V +-------------------------------------+ | +-------+ +-----+ +-------+ | | | Radio |----| MCU |----|Sensors| | | +-------+ +-----+ +-------+ | +-------------------------------------+
TinyOS 2.x is built on a tree-layered hardware abstraction architecture (HAA)[TEP2]. This architecture separates the code for each platform into distinct layers:
- the Hardware Independent Layer (HIL)
- the Hardware Adaptation Layer (HAL)
- the Hardware Presentation Layer (HPL)
A platform is built from bottom up, starting with the HPL level, building HAL and HIL layers on top. Platform independent applications are written using HIL level interfaces, allowing them to move easily from platform to platform. While applications can target a platform specific HAL layer for finer control of hardware specific features, this will could prohibit such an application from being easily portable. An overview of the TinyOS 2 architecture is given in [tos2.0view].
The requirements for the platform implementation is described in TinyOS Enhancement Proposals (TEP). Each TEP covers a particular area and specifies the recommendations within that area, some of which are relevant for platforms. While no specific label or designation is given to platforms adhering to the set of TEPs, [TEP1] states: "Developers desiring to add code (or TEPs) to TinyOS SHOULD follow all current BCPs (Best Current Practice)". At the time of writing no TEP has been awarded this designation or been finalized and we will refer to the drafts as they are.
This document will not go through each of the requirements, but merely outline how to build a basic functional platform. For further information see "TinyOS 2.0 Overview" [tos2.0view] or the TEP list on the TinyOS website http://www.tinyos.net.
The core of TinyOS is maintained by a set of working groups that govern specific parts of the source code. New project can benefit from the contrib section of TinyOS. This is a separate section of the website and source repository maintained more loosely than the core of TinyOS. It is intended for sharing code at an early stage or code that may not gain the same popularity as the core.
New projects request a directory in this repository by following a simple procedure on the TinyOS contrib web page
In contrib is a skeleton project skel that provides the most basic framework for setting up a new platform, MCU, etc.
A TinyOS platform provides the code and tool chain definitions that enable an application writer to implement an application for a mote. A platform in TinyOS exposes some or all of the features of a particular physical mote device to TinyOS applications - it refers to an entire system, not a single chip. In order to write programs for a device using TinyOS a platform for that device must exist within TinyOS.
A physical platform is comprised of a set of chips. Similarly a TinyOS platform is the collection of the components representing these chips (corresponding to drivers) Common chips can be shared among platforms and implementing a new platform could simply mean wiring existing components in a new way. If the chips that make up the platform are not supported by TinyOS implementing the new platform consists if implementing components for those chips (much like implementing drivers).
Platforms are discovered at compile time by the TinyOS tool chain and a new platform placed in the search path will be discovered automatically. In addition sensor boards can be defined in a very similar manner, however we will not cover sensor boards, see [TEP109] for details. Defining a new platform boils down to 3 things:
- definitions of the chips that make up the platform,
- platform definitions (combining chips to a platform) and,
- the tool chain or make definitions.
The code for a TinyOS platform is spread out in a few locations of the TinyOS tree depending based on those 3 categories. Below is an overview of the locations and some of the files we will be needing in the following (for further information see see "Coding Conventions" [TEP3] and the "README" files in each directory).
Through this TEP we will use the terms PlatformX and MCUX to denote the new generic platform and MCU being created:
tos +--chips 1. Chip definitions | +--chipX +--platforms | +--platformX 2. Platform definitions | +--PlatformP/PlatformC | +--PlatformLeds example component | +--.platform | +--hardware.h | +--chips | +--MCUX Platform specific features | +--chipX +--sensorboards | +--boardX | +--.sensor +--support +--make 3. Make definitions +--platformX.target platformX make targets +--MCUX +--MCUX.rules make rules for MCUX +--install.extra additional target for MCUX
In the following we will briefly introduce each of the parts and describe them in more detail in sections 2 through 4.
Each of the chips that provide software accessible functionality must have definitions present in the chips directory sensors, radios, micro controllers (MCU) alike. Each chip is assigned a separate directory under tos/chips. This directory contains chip specific interfaces (HPL and HAL interfaces) and their implementations as well as implementations of the hardware independent interface (HIL).
Some chips, MCUs in particular, contain distinct subsystems, such as uart, timer, A/D converter, SPI, and so forth. These subsystems are often put in a sub directory of their own within the chip-specific directory.
If some feature of a chip is available or used only on a particular platform, the platform directory can contain code that is specific to this combination of chip and platform, say pin assignments, interrupt assignments, etc. For example such additions would be placed in tos/platforms/platformX/chips/chipX for PlatformX.
The platform is the piece of the puzzle that ties the components corresponding to physical chips (drivers) together to form a platform. The platform ties together the code that exposes the features of the platform to TinyOS programs. In practise this is done by i) including code for each of the chips and ii) by providing any additional code that is specific to this particular platform.
A platform PlatformX would be placed in the directory tos/platforms/platformX/ and code for subsystems reside in further sub directories. Also in this directory is the .platform file that sets up include paths and more (see Section 3).
An empty platform with no code (null) is provided and serves as an example for other platforms.
The build system for TinyOS is written using GNU Make [1]. The build system controls the process from pre-processing a TinyOS application into a single C file and to pass this file to the appropriate compiler and other tools. The make system is documented in support/make/README and in TinyOS 2 Tutorial Lesson 10[TUT10].
The make system is located in the support directory. This directory contains a platform definition and Make rules to build an application for this platform (see Section 2).
| [1] | http://www.gnu.org/software/make/ |
Before describing each of the subsystems, we will show a simple check list. The absolute minimal TinyOS platform would have to provide the following resources, given a PlatformX with MCUX:
The major components in the tool chain of TinyOS are i) the compiler and ii) the build system that uses the compiler to produce an executable binary or hex file. The first is installed separately, while the second is part of the TinyOS source code. The compile process transforms a set of nesC files into a binary executable or hex file. Involved in this process is set of separate tools that are linked in a chain. We will briefly cover this chain in a moment, but a detailed description is beyond the scope of this TEP.
The make system is split in two: a general part and a platform specific part. Section 3.1 will introduce the general mechanism and Section 3.2 will cover how to introduce a new platform in the tool chain.
The process of the build system is depicted below. This system feeds the source code through the tools to produce an executable or hex file for uploading to the platform. The nesC pre-compiler is split in two tools ncc an nescc. These two tools are used to assemble nesC source files into a single C file which is compiled using a regular C compiler. This requires that a C compiler is available for a given platform and that this compiler accepts the dialect produced by nesC.
TinyOS application | | V +------+ +-----+ +---------+ +------------+ | ncc | app.c | | Binary | | app.hex | | | + |------>| GCC |------->| objdump |-------->| programmer | | nesC | | | | | | | +------+ +-----+ +---------+ +------------+ | | V Target platform
The core TinyOS platforms are centered around GCC, this includes the telos family, mica family and intelmote2. The nesC compiler expects code resembling GCC C-dialect and also outputs code in GCC C-dialect. The current TinyOS platforms are supported by GCC, but for some processor architectures GCC is not available (e.g. Motorola HCS08, Intel MCS51).
Porting to platforms that are GCC supported can benefit from the existing tool flow, while porting to other platforms requires some effort. A straight forward solution adopted for these platforms is to post-process the C files produced by nesC to fit the needs of a specific compiler, see TEP121 for an example of such a solution.
TinyOS controls the build process using make. The global make file searches certain locations to find make definitions for all available platforms. In order to make a new platform available to the TinyOS make system, a few files must be created in particular locations. These files will be read by the global make system and exposed to the users by make targets. Often the required rules are tied to a particular MCU that is shared among several platforms and TinyOS leverages this fact by creating a light-weight .target file pointing to the appropriate rules in a .rules file. The make system is documented in support/make/README and in TinyOS 2 Tutorial Lesson 10[TUT10].
The make system looks for .target files in support/make and the directories listed in the environment variable TOSMAKE_PATH. Each of the files found contain make targets for one TinyOS platform. The target files usually do not contain the rules to build the binary files, but include the appropriate rules from a .rules file, located in a sub directory for the appropriate MCU architecture (e.g. avr for the ATMega128 used by Mica). In this way many platforms share the build rules, but have different .target files. In addition .extra targets can be used to define helper targets such as install or clean.
Setting up the make system, requires two steps (Section 3.2.1 gives an example):
- Creating a platformX.target file that allows the make system to discover the new platform. This file must contain a make rule with the name of the platform. Further this target must depend on the targets given in the variable BUILD_DEPS - this variable contains the remainder of targets to be build during the build process.
- Creating a .rules file in a sub diretory of support/make. Each file contain the actual target for producing the binaries, hex files, etc. for one platform. They are assembled in the BUILD_DEPS variable.
We will cover these two files next.
As mentioned above TinyOS searches for targets in the support/make directory of the TinyOS source code and in the directories listed in the environment variable TOSMAKE_PATH. A .target file for the platform must exist in one of these locations. The .target usually only sets up variables related to this platform and provide a target named after the platform, this target depend on other rules to build the binaries. These rules are included by calling TOSMake_include_platform. As an example the mica2.target is listed below:
PLATFORM = mica2 SENSORBOARD ?= micasb PROGRAMMER_PART ?= -dpart=ATmega128 --wr_fuse_e=ff PFLAGS += -finline-limit=100000 AVR_FUSE_H ?= 0xd9 $(call TOSMake_include_platform,avr) mica2: $(BUILD_DEPS) @:
Pay attention to the call to TOSMake_include_platform,avr this call includes .rules files in support/make or any sub directory of TOSHMAKE_PATH named avr.
The .rules file contain the make rules for building the target binary. If a MCU implementation already exists for a new platform, simply pointing to this .rules from the corresponding .target is sufficient. If not the .rules file must be built for a new MCU architecture.
TOSMake_include_platform expects a sub directory with a rule file of the form avr/avr.rules. The call also includes additional .rules and .extra files present in that sub directory. See support/make/README for details.
For example a simplified .rules file could look like this (from avr/avr.rules):
... BUILD_DEPS = srec tosimage srec: exe FORCE $(OBJCOPY) --output-target=srec $(MAIN_EXE) $(MAIN_SREC) tosimage: ihex build_tosimage FORCE @: exe: builddir $(BUILD_EXTRA_DEPS) FORCE @echo " compiling $(COMPONENT) to a $(PLATFORM) binary" $(NCC) -o $(MAIN_EXE) $(OPTFLAGS) $(PFLAGS) $(CFLAGS) $(COMPONENT).nc $(LIBS) $(LDFLAGS) ...
A TinyOS platform is a collection of components corresponding to a physical devices (a collection of drivers). A platform is constructed by defining which components make up the platform and by providing any additional platform specific components. The content of a platform is not covered by a TEP at the time of writing and the following is based on the available tutorials, READMEs and the current consensus.
The platform definitions for a PlatformX are located in tos/platforms/platformX and contain 3 major elements:
- The .platform file containing include paths and other arguments for nesC
- Platform boot procedure: PlatformP/PlatformC
- Platform specific code, including a header for hardware specific funtions (hardware.h) and code that is specific to the combination of chip and platform (e.g. pin assignments, modifications, etc.).
In the following we will describe each of these in more detail, below is a depiction of a fictuous platform and the required definitions.
Platform: .platform include MCU driver +-------------------------+ include Radio driver | | include Sensors driver | Chips: | | +-------+ | PlatformP | | Radio | | Initialize MCU | +--+----+ | Initialize Sensor | +-----+ | | Initialize Radio | | MCU +------+ | | +-----+ | | hardware.h | +--+----+ | Include MCU HW macros | | Leds | | | +-------+ | HIL interfaces, eg: | | PlatformLeds +-------------------------+
All the files we describe here must be found in a common directory named after the platform; we call this a platform directory. This directory must be found in the TinyOS tool chain search path for example tos/platforms (or found in TOSHMAKE_PATH see Section 3.2.1). For example a platform named PlatformX could be placed in the directory tos/platforms/platformX.
All platform directories must carry a .platform file, this file defines what makes up the platform. This file carries instructions for the make system on where to locate the drivers for each of the components of the platform. The definitions are read in a two step process: the file is read by the ncc script that passes the appropriate arguments to the nesC pre-processor[nescman]. The .platform file is written as a Perl script interpreted by ncc.
The file is documented in form of the README file in the platforms directory (tos/platforms), and the source code of the ncc script found in the TinyOS distribution. Valuable information can also be found in [TEP106], [TEP109], TinyOS 2 Tutorial Lesson 10[TUT10].
In addition to setting up include paths for nesC other arguments can be passed on. In particular the components to be used for the scheduler are selected with the '-fnesc-scheduler' command line argument (see [TEP106]). The include paths are passed on using the '-I' command line argument covered in [TEP109].
As an example, an abbreviated .platform file for the mica2 platform looks like this:
push( @includes, qw( %T/platforms/mica %T/platforms/mica2/chips/cc1000 %T/chips/cc1000 %T/chips/atm128 %T/chips/atm128/adc %T/chips/atm128/pins %T/chips/atm128/spi %T/chips/atm128/timer %T/lib/timer %T/lib/serial %T/lib/power ) ); @opts = qw( -gcc=avr-gcc -mmcu=atmega128 -fnesc-target=avr -fnesc-no-debug -fnesc-scheduler=TinySchedulerC,TinySchedulerC.TaskBasic,TaskBasic,TaskBasic,runTask,postTask );
The PlatformP and PlatformC components are responsible for booting this platform to a usable state. In general this usually means things like calibrating clock and initializing I/O pins. If this platform requires that some devices are initialized in a particular order this can be implemented in a platform dependent way here. The boot process covered in [TEP107].
Most hardware peripherals require an initialization procedure of some sort. For most peripheral devices this procedure is only required when the device is in use and can be left out if the device is unused. TinyOS accomplishes this by providing a few initialization call backs interfaces. When a given component is included it wires an initialization procedure to one of these interfaces. In this way the procedure will only be included when the component is included, this process is known as auto wiring[TOSPRG].
The boot sequence calls two initialization interfaces in the following order: PlatformC.Init and MainC.SoftwareInit. PlatformC.Init must take care of initializing the hardware to an operable state and initialization that has hidden dependencies must occur here. Other components are initialized as part of SoftwareInit and the orderign is determined at compile time.
Common tasks in PlatformC.Init include clock calibration and IO pins. However this component can be used to provide greater control of the boot process if required. Consider for example that some component which is initialized in SoftwareInit requires that some other component has been initialized previously - lets say that the radio must be initialized prior to the radio stack or that a component prints a message to the UART during boot. How can this order be ensured? One solution is to provide an additional initialization handle prior to SoftwareInit and wire such procedures to this handle. Below is an example from the Mica mote family using the MoteInit interface. Components that must be initialized early in the boot process is wired to this interface. If greater level of control is required this strategy can be trivially be expanded to further levels of interfaces for example MoteInit1 being initialized prior to MoteInit2, this strategy is chosen by the MSP430 implementation.
Below is depicted the PlatformC component from the Mica family of platforms.
#include "hardware.h" configuration PlatformC { provides { interface Init; /** * Provides calibration information for other components. */ interface Atm128Calibrate; } uses interface Init as SubInit; } implementation { components PlatformP, MotePlatformC, MeasureClockC; Init = PlatformP; Atm128Calibrate = MeasureClockC; PlatformP.MeasureClock -> MeasureClockC; PlatformP.MoteInit -> MotePlatformC; MotePlatformC.SubInit = SubInit; }
Below is depicted the PlatformP component from the Mica family of platforms.
module PlatformP { provides interface Init; uses interface Init as MoteInit; uses interface Init as MeasureClock; } implementation { void power_init() { ... } command error_t Init.init() { error_t ok; ok = call MeasureClock.init(); ok = ecombine(ok, call MoteInit.init()); return ok; } }
Below is an example from mica/PlatformLedsC.nc wiring to the platform specific MoteInit interface.
configuration PlatformLedsC { provides interface GeneralIO as Led0; ... uses interface Init; } implementation { components HplAtm128GeneralIOC as IO; components PlatformP; Init = PlatformP.MoteInit; ...
In addition to PlatformP/PlatformC the platform directory contain additional code that is specific to this platform. First this could be code that ties platform independent resources to particular instances on this platform, second it could be code that is only relevant on this particular platform (e.g. the clock rate of this platform). For example the LEDs are a an example of the first: most platform have a few LEDs, and the particular pin on this platform is tied to the platform independent implementation using PlatformLedsC.
TinyOS requires that the header hardware.h is present while other component can be named freely.
TinyOS relies on a few C-header files being present for each platform. These headers are then automatically included from the respective parts of the TinyOS system. TinyOS expects that the following files are present and that certain properties are defined in them.
The hardware.h header file is included by tos/system/MainC.nc and usually in turn includes a MCU specific header file, with a few required macros (such as avr128hardware.h, see Section 5.1.1). The header is documented in TinyOS 2 Tutorial Lesson 10[TUT10]
In addition the hardware.h file can set flags that are not related to the hardware in general, but to this platform (e.g. clock rate). Below is a snippet from mica2/hardware.h
#ifndef MHZ /* Clock rate is ~8MHz except if specified by user (this value must be a power of 2, see MicaTimer.h and MeasureClockC.nc) */ #define MHZ 8 #endif #include <atm128hardware.h> enum { PLATFORM_BAUDRATE = 57600L }; ...
As part of the TinyOS 2 message buffer abstraction[TEP111], TinyOS includes the header platform_message.h from the internal TinyOS header message.h. This header is only strictly required for platforms wishing to use the message_t abstraction - this is not described further in this TEP, but is used widely throughout TinyOS (See [TEP111] for details). The is expected to define the structures: message_header_t, message_footer_t, and message_metadata_t which are used to fill out the generic message_t structure.
Below is an example from the mica2 platform_message.h
typedef union message_header { cc1000_header_t cc1k; serial_header_t serial; } message_header_t; typedef union message_footer { cc1000_footer_t cc1k; } message_footer_t; typedef union message_metadata { cc1000_metadata_t cc1k; } message_metadata_t;
The code for platform dependent features also resides in the platform directory. If the code can be tied to a particular chip it can be placed in a separate directory below the chips directory. As an example the following section of micaz/chips/cc2420/HplCC2420PinsC.nc ties specific pins to general names on the MicaZ platform.
configuration HplCC2420PinsC { provides { interface GeneralIO as CCA; interface GeneralIO as CSN; interface GeneralIO as FIFO; interface GeneralIO as FIFOP; interface GeneralIO as RSTN; interface GeneralIO as SFD; interface GeneralIO as VREN; } } implementation { components HplAtm128GeneralIOC as IO; CCA = IO.PortD6; CSN = IO.PortB0; FIFO = IO.PortB7; FIFOP = IO.PortE6; RSTN = IO.PortA6; SFD = IO.PortD4; VREN = IO.PortA5; }
The functionality of each chip is provided by a set of one or more interfaces and one or more components, in traditional terms this makes up a driver. Each chip is assigned a sub directory in the the tos/chips directory. All code that define the functionality of a chip is located here regardless of the type of chip (MCU, radio, etc.). In addition MCU's group the code related to separate sub systems into further sub directories (e.g. tos/chips/atm128/timer).
In this section we will go trough some of the peripherals commonly built into MCUs, but we will not go trough other chips such as sensors or radio.
Apart from the drivers for each of the peripheral units, a few additional definitions are required for the internals of the MCU. This includes i) atomic begin/end and ii) low power mode. The first is defined in the header hardware.h and the latter component MCUSleepC.
Each architecture defines a set of required and useful macros in a header filed named after the architecture (for example atm128hardware.h for ATMega128). This header is then in turn included from hardware.h in the platform directory (See Section 4.3.1).
A few of the macros are required by nesC code generation. nesC will output code using these macros and they must be defined in advance, other useful macros such as interrupt handlers on this particular platform can be defined here as well. The required macros are:
- __nesc_enable_interrupt / __nesc_disable_interrupt
- __nesc_atomic_start / __nesc_atomic_end
Below is a few examples from atm128hardware.h
/* We need slightly different defs than SIGNAL, INTERRUPT */ #define AVR_ATOMIC_HANDLER(signame) \ void signame() __attribute__ ((signal)) @atomic_hwevent() @C() #define AVR_NONATOMIC_HANDLER(signame) \ void signame() __attribute__ ((interrupt)) @hwevent() @C() ... inline void __nesc_enable_interrupt() { sei(); } inline void __nesc_disable_interrupt() { cli(); } ... inline __nesc_atomic_t __nesc_atomic_start(void) @spontaneous() { __nesc_atomic_t result = SREG; __nesc_disable_interrupt(); asm volatile("" : : : "memory"); return result; } /* Restores interrupt mask to original state. */ inline void __nesc_atomic_end(__nesc_atomic_t original_SREG) @spontaneous() { asm volatile("" : : : "memory"); SREG = original_SREG; }
TinyOS manages the power state of the MCU through a few interfaces. These interfaces allow components to signal how and when this platform should enter low power mode. Each new MCU in TinyOS must implement the MCUSleepC component that provide the McuSleep and McuPowerState interfaces.
The TinyOS scheduler calls McuSleep.sleep() when it runs out of tasks to start. The purpose of this function is to make the MCU enter the appropriate sleep mode. The call to McuSleep.sleep() is made from within an atomic section making it essential that sleep() enables interrupts before entering sleep mode! If the interrupts not enabled prior to entering sleep mode the MCU will not be able to power back up.
A dummy MCU sleep component that does not enter sleep mode, but merely switches interrupts on and off is shown below. This ensures that the platform will not lock up even without proper sleep support.
#include "hardware.h" module McuSleepC { provides interface McuSleep; provides interface McuPowerState; uses interface McuPowerOverride; } implementation { async command void McuSleep.sleep() { __nesc_enable_interrupt(); // Enter sleep here __nesc_disable_interrupt(); } async command void McuPowerState.update() { } }
Virtually all micro controllers feature a set of input output (I/O) pins. The features of these pins is often configurable and often some pins only support a subset of features. The HIL level interface for TinyOS is described in [TEP117] and uses two interface to describe general purpose I/O pins common to many MCUs:
While these interfaces are aimed at the HIL level some platforms use the GeneralIO and GpioInterrupt interface to represent the HPL level (atm128 for example) and others platforms define their own interface to capture the entire functionality (msp430, pxa27x for example).
[TEP117] states that each platform must provide the general IO pins of that platform through the GeneralIO interface and should do this though the component GeneralIOC. It is however not clear how the entire set of pins should be provided - this could be in the form of a list of pins, group of pins, a generic component, etc.
The pin implementations are usually found in the pins sub directory for a particular MCU (e.g. msp430/pins for MSP430 pin implementation).
The MSP430 implementation builds the platform independent pin implementation as a stack of components starting with a platform specific component for each pin.
| GeneralIO +---------------------+ | Msp430GpioC | +---------------------+ | HplMsp430GeneralIO +---------------------+ | HplMsp430GeneralIOC | +---------------------+ | HplMsp430GeneralIO +---------------------+ | HplMsp430GeneralIOP | +---------------------+
At the bottom the component HplMsp430GeneralIOP provides a general implementation of one Msp430 pin using the HplMsp430GeneralIO interface.
These are then instantiated from HplMsp430GeneralIOC (abbreviated):
configuration HplMsp430GeneralIOC { provides interface HplMsp430GeneralIO as Port10; provides interface HplMsp430GeneralIO as Port11; ... } implementation { components new HplMsp430GeneralIOP(P1IN_, P1OUT_, P1DIR_, P1SEL_, 0) as P10, new HplMsp430GeneralIOP(P1IN_, P1OUT_, P1DIR_, P1SEL_, 1) as P11, ... Port10 = P10; Port11 = P11; ...
And finally these are transformed from the interface HplMsp430GeneralIO to the platform independent GeneralIO using the generic component Msp430GpioC (abbreviated):
generic module Msp430GpioC() { provides interface GeneralIO; uses interface HplMsp430GeneralIO as HplGeneralIO; } implementation { async command void GeneralIO.set() { call HplGeneralIO.set(); } async command void GeneralIO.clr() { call HplGeneralIO.clr(); } async command void GeneralIO.toggle() { call HplGeneralIO.toggle(); } ...
Having a few leds on a platform is quite common and TinyOS supports three leds in a platform independent manner. Three leds are provided through the LedsC component regardless of the amount of leds available on the platform. The LED implementation is not covered by a TEP at the time of writing, but the general consensus between most platforms seems to be to provide access to 3 LEDs through the component PlatformLedsC. This component is then used by LedC and LedP (from tos/system) to provide a platform independent Led interface.
The PlatformLedsC implementation is found in the platform directory of each platform (e.g. tos/platforms/mica2 for mica2). The consensus is as follows:
configuration PlatformLedsC { provides interface GeneralIO as Led0; provides interface GeneralIO as Led1; provides interface GeneralIO as Led2; uses interface Init; } implementation { components HplAtm128GeneralIOC as IO; components new NoPinC(); components PlatformP; Init = PlatformP.MoteInit; Led0 = IO.PortA2; // Pin A2 = Red LED Led1 = NoPinC; Led2 = NoPinC; }
The Led interface described above is not specified in a TEP, though at the time of writing most platforms seem to follow this pattern. Not being covered by a TEP leads to a few uncertainties:
The timer subsystem in TinyOS 2 is described in [TEP102] the TEP specifies interfaces at HAL and HIL levels that a platform must adhere to. The timer does not cover the possible design choices at the HPL level. The timers defined in this TEP are described in terms of width of the underlying counters (e.g. 8, 16, 32 bit) and in the tick period or frequency denoted precision (e.g. 10 kHz, 1 ms, 1 us). The timer subsystem is provided through a set of hardware independent interfaces and a set of recommended configuration modules. As such some features of a particular device may not be available in a device independent manner.
The functionality commonly seen in MCU timer units is often split in 3 parts: control, timer/counter, capture/compare(trigger). Timer control in is inherently platform specific and is not covered by a TEP. The timer [TEP102] covers timer/counter while capture/compare is covered by [TEP117]. From the TEPs it is not clear how capture/compare and timer/counter relate to each other even though they are likely to refer to the same time base. The calibration of the system clock is often connected with the timer system and lives in the timer directory, but it is not covered in [TEP102].
The timer implementation for a given MCU is placed in the timer sub directory of the directory for a given MCU (e.g. tos/chips/avr/timer). Often clock initialization components are placed in the same directory, but these are not covered by the TEPs.
TEP117 follows the 3 layer architecture and separates the platform dependent and independent abstractions. It poses not restrictions on the HPL layer, but provides a suggested HAL layer and requirements at the HIL level. It defines a set of interfaces and precisions that are used at the HAL and HIL levels.
The common features of a timer are separated into a set of interfaces, corresponding roughly to common features in MCU timer units. The interfaces covered by the [TEP102] are (capture from [TEP117]):
The precisions defined in [TEP117] are defined as "binary" meaning 1024 parts of a second. Platforms must provide these precisions (if possible) regardless of the underlying system frequency (i.e. this could be a power of 10).
The features of the underlying hardware timers are generally exposed using one or more hardware specific interfaces. Many MCU provide a rich a set of different timer units varying in timer width, frequency and features.
Many MCUs provides features that are quite close to the features described by the interfaces above. The HPL layer exposes these features and the layers above utilize the available hardware and virtualize the features if necessary.
Consider for example generating events at a specific time. Often a timer unit has a single counter and a few compare registers that generate interrupts. The counter and compare registers often translate relative straightforward to Counter and Alarm interfaces.
Each platform should expose a hardware timer of precision P and width W as Counter${P}${W}C, Alarm${P}${W}C(). For example an 8 bit, 32.768 kHz timer should be exposed as Counter32khz8C and Alarm32khz8C
Alarm/Counters come in pairs and refer to a particular hardware unit, while there is only one counter there is commonly multiple compare registers. Alarm is a generic component and each instantiation must provide an independent alarm allocating more Alarm components than available compare register should provide a compile time error.
Each platform must expose the following components that provide specific width and precision that are guaranteed to exist on TEP compliant platforms.
- HilTimerMilliC A 32 bit Timer interface of TMilli precision
- BusyWaitMicroC A BusyWait interface of TMicro precision
Implementing the timers for TinyOS in short consists of utilizing the available HW timer features to provide TinyOS style timers interfaces. In general the approach taken by existing platforms is to create a set of HPL level timer and control interfaces that export the available hardware features and adapt these to specific precisions and widths at the HAL level. However the specific HPL level design choices differ from platform to platform.
For example one could export all timers as a simple list, a component for each timer, a parameterised interface, etc. Similarly for the control features this could be provided with the timer interfaces or kept as a separate interface. In the following we will go through a few examples and point out their differences.
The ATMega128l implementation (atm128) exports the system timers one component each. Each component provide 4 interfaces - one for each of the functions of the unit: timer, capture, compare and control. The timer, capture, and compare interfaces are generic based on the width (either 8 or 16 bit) while two separate control interfaces are provided.
Depicted below is a diagram of how HplAtm128Timer1C could be stacked to provide platform independent interfaces (not shown are HplAtm128Timer0Async, HplAtm128Timer2, HplAtm128Timer3):
+------------------------------------------------+ | HplAtm128Timer1C | +-----+-------------------+-----------------+----+ HplAtm128Capture| HplAtm128Timer| HplAtm128Compare| | | | +----------+---------+ | | | Atm128GpioCaptureC | | | +----------+---------+ | | | +-+-----------------+--+ GpioCapture| | Atm128AlarmC | | +----------+-----------+ | Alarm|
The hardware features is exported using 3 interfaces: HplAtm128Timer, HplAtm128Compare and HplAtm128Capture.
interface HplAtm128Timer<timer_size> { async command timer_size get(); async command void set( timer_size t ); async event void overflow(); async command void reset(); async command void start(); ... interface HplAtm128Compare<size_type> { async command size_type get(); async command void set(size_type t); async event void fired(); //<! Signalled on compare interrupt async command void reset(); ... interface HplAtm128Capture<size_type> { async command size_type get(); async command void set(size_type t); async event void captured(size_type t); async command void reset();
#include <Atm128Timer.h> interface HplAtm128TimerCtrl8 { /// Timer control register: Direct access async command Atm128TimerControl_t getControl(); async command void setControl( Atm128TimerControl_t control ); /// Interrupt mask register: Direct access async command Atm128_TIMSK_t getInterruptMask(); async command void setInterruptMask( Atm128_TIMSK_t mask); /// Interrupt flag register: Direct access async command Atm128_TIFR_t getInterruptFlag(); async command void setInterruptFlag( Atm128_TIFR_t flags ); }
Each of the hardware timers are exported in one component for example 'HplAtm128Timer1P':
#include <Atm128Timer.h> module HplAtm128Timer1P { provides { // 16-bit Timers interface HplAtm128Timer<uint16_t> as Timer; interface HplAtm128TimerCtrl16 as TimerCtrl; interface HplAtm128Capture<uint16_t> as Capture; interface HplAtm128Compare<uint16_t> as CompareA; interface HplAtm128Compare<uint16_t> as CompareB; interface HplAtm128Compare<uint16_t> as CompareC; } uses interface HplAtm128TimerCtrl8 as Timer0Ctrl; } implementation { //=== Read the current timer value. =================================== async command uint16_t Timer.get() { return TCNT1; } //=== Set/clear the current timer value. ============================== async command void Timer.set(uint16_t t) { TCNT1 = t; } ...
The MSP430 features two very similar (but not identical) timers. Both timers are provided through the same interfaces in a way similar to ATMega128l: 'Msp430Timer', 'Msp430Capture' 'Msp430Compare', 'Msp430TimerControl'. All timer interfaces (for both timers) are accessed through the component Msp430TimerC.
The Msp430TimerControl is show below. It is slightly different than the ATMega equivalent - notice that 'setControl' accepts a struct with configuration parameters instead of setting these with a command each.
#include "Msp430Timer.h" interface Msp430TimerControl { async command msp430_compare_control_t getControl(); async command bool isInterruptPending(); async command void clearPendingInterrupt(); async command void setControl(msp430_compare_control_t control ); async command void setControlAsCompare(); async command void setControlAsCapture(uint8_t cm); async command void enableEvents(); async command void disableEvents(); async command bool areEventsEnabled(); }
Each timer is implemented through the generic component 'Msp430TimerP' that is instantiated for each timer in 'Msp430TimerC':
configuration Msp430TimerC { provides interface Msp430Timer as TimerA; provides interface Msp430TimerControl as ControlA0; provides interface Msp430TimerControl as ControlA1; provides interface Msp430TimerControl as ControlA2; provides interface Msp430Compare as CompareA0; provides interface Msp430Compare as CompareA1; provides interface Msp430Compare as CompareA2; provides interface Msp430Capture as CaptureA0; provides interface Msp430Capture as CaptureA1; provides interface Msp430Capture as CaptureA2; ... } implementation { components new Msp430TimerP( TAIV_, TAR_, TACTL_, TAIFG, TACLR, TAIE, TASSEL0, TASSEL1, FALSE ) as Msp430TimerA , new Msp430TimerP( TBIV_, TBR_, TBCTL_, TBIFG, TBCLR, TBIE, TBSSEL0, TBSSEL1, TRUE ) as Msp430TimerB , new Msp430TimerCapComP( TACCTL0_, TACCR0_ ) as Msp430TimerA0 , new Msp430TimerCapComP( TACCTL1_, TACCR1_ ) as Msp430TimerA1 , new Msp430TimerCapComP( TACCTL2_, TACCR2_ ) as Msp430TimerA2 ...
The PXA27x (XScale) platform provides a component for each of the timers classes on the system. Each component provides a few interfaces that exposes all features of that unit. Each interface combines timer and control interface features. For example 'HplPXA27xOSTimerC' provides 12 instances of the 'HplPXA27xOSTimer' interface and one instace 'HplPXA27xOSTimerWatchdog'. Similarly for 'HplPXA27xSleep' and 'HplPXA27xWatchdog'.
interface HplPXA27xOSTimer { async command void setOSCR(uint32_t val); async command uint32_t getOSCR(); ... async event void fired(); }
All the OS timers are exported through HplPXA27xOSTimerC
configuration HplPXA27xOSTimerC { provides { interface Init; interface HplPXA27xOSTimer as OST0; interface HplPXA27xOSTimer as OST0M1; interface HplPXA27xOSTimer as OST0M2; interface HplPXA27xOSTimer as OST0M3; ... implementation { components HplPXA27xOSTimerM, HplPXA27xInterruptM; Init = HplPXA27xOSTimerM; OST0 = HplPXA27xOSTimerM.PXA27xOST[0]; OST0M1 = HplPXA27xOSTimerM.PXA27xOST[1]; OST0M2 = HplPXA27xOSTimerM.PXA27xOST[2]; OST0M3 = HplPXA27xOSTimerM.PXA27xOST[3]; ...
These interfaces are further abstracted through 'HalPXA27xOSTimerMapC' as a parameterised interface:
configuration HalPXA27xOSTimerMapC { provides { interface Init; interface HplPXA27xOSTimer as OSTChnl[uint8_t id]; } } implementation { components HplPXA27xOSTimerC; Init = HplPXA27xOSTimerC; OSTChnl[0] = HplPXA27xOSTimerC.OST4; OSTChnl[1] = HplPXA27xOSTimerC.OST5; OSTChnl[2] = HplPXA27xOSTimerC.OST6; ...
While the TEP is clear on many points there are few that are left up to the implementer. The relation between timers and capture events is unclear and covered in two TEPs. Capture refers to timers[TEP102] but the reverse is not clear[TEP102]. This has a few implications for the timer/capture relationship:
Most modern microprocessors provide a selection of standard I/O bus units such as serial (UART or USART), I2C, SPI, etc. The drivers for the available buses are usually put in a sub directory for the MCU (e.g. chip/atm128/spi for SPI on ATMega128l).
There are a few TEP that cover different buses in TinyOS, and low level serial communication:
On some hardware platforms a single I/O unit is shared among a number of buses. The MSP430 for example implements SPI, I2C and USART in a single USART unit that can only operate in one mode at a time. In such cases the single hardware unit must be shared among the drivers.
Serial communication in TinyOS 2.x is implemented as a serial communications stack with a UART or USART at the bottom. The bottom layer is covered in [TEP113] and [TEP117]. TEP117 states that each platform must provide access to a serial port through the 'SerialByteComm' interface from the component UartC. However UartC is not provided by any platforms at the time of writing. There seems to be a consensus to build the component 'PlatformSerialC' providing the 'UartStream' and 'StdControl' interfaces. Either component will be placed in the platform directory (e.g. tos/platforms/mica2 for mica2). The serial stack is built upon 'PlatformSerialC' and this component will be required to take advantage of the serial stack.
[TEP117] defines 'UartStream' and 'UartByte' to access the a UART multiple bytes at a time and one byte at a time (synchronously), while [TEP113] defines 'UartByte' to send and receive one byte at a time (asynchronously).
SPI and I2C buses are provided through straightforward interfaces that match the functionality of the buses closely.
interface SpiByte { async command uint8_t write( uint8_t tx ); }
interface SpiPacket { async command error_t send( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len ); async event void sendDone( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len, error_t error ); }
interface I2CPacket<addr_size> { async command error_t read(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data); async command error_t write(i2c_flags_t flags, uint16_t addr, uint8_t length, uint8_t* data); async event void readDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data); async event void writeDone(error_t error, uint16_t addr, uint8_t length, uint8_t* data); }
| [TEP1] | TEP 1: TEP Structure and Keywords <http://www.tinyos.net/tinyos-2.x/doc/html/tep1.html> |
| [TEP2] | TEP 2: Hardware Abstraction Architecture <http://www.tinyos.net/tinyos-2.x/doc/html/tep2.html> |
| [TEP3] | TEP 3: Coding Standard <http://www.tinyos.net/tinyos-2.x/doc/html/tep3.html> |
| [TEP102] | TEP 102: Timers <http://www.tinyos.net/tinyos-2.x/doc/html/tep102.html> |
| [TEP106] | TEP 106: Schedulers and Tasks <http://www.tinyos.net/tinyos-2.x/doc/html/tep106.html> |
| [TEP107] | TEP 107: TinyOS 2.x Boot Sequence <http://www.tinyos.net/tinyos-2.x/doc/html/tep107.html> |
| [TEP109] | TEP 109: Sensors and Sensor Boards <http://www.tinyos.net/tinyos-2.x/doc/html/tep109.html> |
| [TEP111] | TEP 111: message_t <http://www.tinyos.net/tinyos-2.x/doc/html/tep111.html> |
| [TEP113] | TEP 113: Serial Communication <http://www.tinyos.net/tinyos-2.x/doc/html/tep113.html> |
| [TEP117] | TEP 117: Low-Level I/O <http://www.tinyos.net/tinyos-2.x/doc/html/tep117.html> |
| [TEP121] | TEP 121: Towards TinyOS for 8051 <http://www.tinyos.net/tinyos-2.x/doc/html/tep121.html> |
| [TOSPRG] | Philip Levis: TinyOS Programming <http://www.tinyos.net/tinyos-2.x/doc/pdf/tinyos-programming.pdf> |
| [tos2.0view] | Philip Levis. "TinyOS 2.0 Overview" Feb 8 2006 <http://www.tinyos.net/tinyos-2.x/doc/html/overview.html> |
| [nescman] | David Gay, Philip Levis, David Culler, Eric Brewer. "NesC 1.2 Language Reference Manual" August 2005 |
| [TUT10] |
LocalWords: TinyOS TEP TEPs nesC |


iperf3 is a tool for active measurements of the maximum achievable bandwidth on IP networks. This is a python wrapper providing a nice and pythonic interface to the tool.


Born: September 11, 2002
Occupation : Student
College: Vishwakarma institute of technology 24'
Branch: Artificial Intelligence and data Science
| SKILLS | |
|---|---|
| HTML | |
| CSS | |
| JAVASCRIPT | |
| FLUTTER |
|
| PYTHON |
Hello, I am Kirti Agarwal. I was born and brought up in Pune in a crazy family of 30 people, well 34 to be precise.🤷🏻♀ I have 2 siblings who are undoubtedly the most annoying creatures on this planet. Nevertheless, I have got the perks of being an elder and younger sibling both together.
I am an introvert who loves exploring new ways of earning money in freetime. I love my family trips and here's a picture of my trip to Ladakh which was indeed the best one.
Speaking of websites and coding, I have always liked development and most of the stuff on this website is an improvised version of my high school websites. Not my best though (time constraints you know 😅). I have used bootstrap 3 here and will be upgrading to bootstrap 5 soon.
ACHIEVEMENTS


{% block title %}
Plataforma Universitaria Compartición Conocimiento
This website template has been designed by Free Website Templates for you, for free. You can replace all this text with your own text. You can remove any link to our website from this website template, you're free to use this website template without linking back to us. If you're having problems editing this website template, then don't hesitate to ask for help on the Forums.