Finished writing and optimizing the code. Very efficient now.
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
39
include/README
Normal file
39
include/README
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
46
lib/README
Normal file
46
lib/README
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||
15
platformio.ini
Normal file
15
platformio.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:due]
|
||||
platform = atmelsam
|
||||
board = due
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
162
src/main.cpp
Normal file
162
src/main.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <Arduino.h>
|
||||
// fm modulation
|
||||
// pin to read in analog audio signal
|
||||
#define sound_in_pin A0
|
||||
// pin to output fm audio signal
|
||||
#define FM_out_pin DAC0
|
||||
#define sync_pin 2
|
||||
|
||||
/**
|
||||
* @brief set up timer 2, channel 2 as a 42 kHz triangle wave.
|
||||
* This is used to generate the FM carrier
|
||||
*/
|
||||
void setup_timer(){
|
||||
pmc_set_writeprotect(false); // disable write protection so we can configure the timer
|
||||
pmc_enable_periph_clk(TC6_IRQn); // enable the clock that runs the timer
|
||||
TC_Configure(TC2, 0, TC_CMR_WAVE | 0x00004000); //configure the counter to be in waveform mode and reset on match with the reset register
|
||||
TC_SetRC(TC2, 0, 0xFFFFFFFF);//997); // reset the counter at this value (once every 23.7 us or 42.1 kHz)
|
||||
TC_Start(TC2, 0); // start the timer
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the given analog channel. THIS DOES NOT WORK UNLESS THE ADC CHANNEL IS INITIALIZED
|
||||
* @param channel the channel to read
|
||||
*/
|
||||
uint32_t fastAnalogRead(adc_channel_num_t analogChannel){
|
||||
uint32_t analog_val = 0;
|
||||
|
||||
analog_val = adc_get_channel_value(ADC, analogChannel);
|
||||
return analog_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set up the ADC to read a 22kHz audio signal
|
||||
* @param analogChannel the analog channel to configure
|
||||
*/
|
||||
void setupADC(adc_channel_num_t analogChannel){
|
||||
// disable write protection so we can configure the ADC
|
||||
adc_set_writeprotect(ADC, 0);
|
||||
// Configure the ADC to read at 1 MHz
|
||||
adc_init(ADC, SystemCoreClock, 1000000, 8);
|
||||
// enable free running mode
|
||||
ADC->ADC_MR |= ADC_MR_FREERUN_ON;
|
||||
// enable the channel
|
||||
adc_enable_channel(ADC, analogChannel);
|
||||
analogRead(analogChannel);
|
||||
//adc_start(ADC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set up the DAC as high speed output.
|
||||
* @param channel The channel to set up.
|
||||
*/
|
||||
void setupDAC(uint32_t channel) {
|
||||
|
||||
// Write the value.
|
||||
if (dacc_get_channel_status(DACC) == 0) {
|
||||
/* Enable clock for DACC */
|
||||
pmc_enable_periph_clk(ID_DACC);
|
||||
|
||||
/* Reset DACC registers */
|
||||
dacc_reset(DACC);
|
||||
|
||||
/* Half word transfer mode */
|
||||
dacc_set_transfer_mode(DACC, 0);
|
||||
|
||||
/* Power save:
|
||||
* sleep mode - 0 (disabled)
|
||||
* fast wakeup - 0 (disabled)
|
||||
*/
|
||||
dacc_set_power_save(DACC, 0, 0);
|
||||
/* Timing:
|
||||
* refresh - 0x08 (1024*8 dacc clocks)
|
||||
* max speed mode - 0 (disabled)
|
||||
* startup time - 0x10 (1024 dacc clocks)
|
||||
*/
|
||||
dacc_set_timing(DACC, 0x08, 1, 0x10);
|
||||
// Ensure the DAC has been set to free running mode
|
||||
//DACC->DACC_MR = DACC->DACC_MR & 0xFFFFFFFE;
|
||||
|
||||
/* Set up analog current */
|
||||
dacc_set_analog_control(DACC, DACC_ACR_IBCTLCH0(0x02) |
|
||||
DACC_ACR_IBCTLCH1(0x02) |
|
||||
DACC_ACR_IBCTLDACCORE(0x01));
|
||||
}
|
||||
|
||||
/* Disable TAG and select output channel chDACC */
|
||||
dacc_set_channel_selection(DACC, channel);
|
||||
|
||||
// Enable the dac if it isn't already enabled
|
||||
if ((dacc_get_channel_status(DACC) & (1 << channel)) == 0) {
|
||||
dacc_enable_channel(DACC, channel);
|
||||
}
|
||||
|
||||
// //return without writing anything if the DACC isn't ready
|
||||
// if ((dacc_get_interrupt_status(DACC) & DACC_ISR_EOC) == 0){
|
||||
// return;
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting setup.");
|
||||
|
||||
// put your setup code here, to run once:
|
||||
pinMode(sound_in_pin, INPUT);
|
||||
pinMode(FM_out_pin, OUTPUT);
|
||||
pinMode(sync_pin, OUTPUT);
|
||||
digitalWrite(sync_pin, LOW);
|
||||
|
||||
// setup the DAC
|
||||
Serial.println("Setting up DAC");
|
||||
setupDAC(0);
|
||||
|
||||
// write to the DAC
|
||||
Serial.println("Zeroing DAC");
|
||||
dacc_write_conversion_data(DACC, 0);
|
||||
|
||||
// set up a timer
|
||||
Serial.println("Setting up timer");
|
||||
setup_timer();
|
||||
|
||||
// set up ADC channel 0
|
||||
Serial.println("Setting up ADC");
|
||||
setupADC(ADC_CHANNEL_0);
|
||||
|
||||
Serial.println("Finished setting up");
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
// sine wave lookup table that goes from 0 to 441. There are 997 points
|
||||
int sine_wave[997] = {2048,2060,2073,2086,2099,2112,2125,2138,2151,2164,2176,2189,2202,2215,2228,2241,2254,2266,2279,2292,2305,2318,2330,2343,2356,2369,2381,2394,2407,2420,2432,2445,2458,2470,2483,2495,2508,2521,2533,2546,2558,2571,2583,2596,2608,2620,2633,2645,2657,2670,2682,2694,2707,2719,2731,2743,2755,2767,2779,2791,2803,2815,2827,2839,2851,2863,2875,2887,2898,2910,2922,2933,2945,2957,2968,2980,2991,3003,3014,3025,3037,3048,3059,3070,3081,3093,3104,3115,3126,3137,3148,3158,3169,3180,3191,3201,3212,3223,3233,3244,3254,3265,3275,3285,3295,3306,3316,3326,3336,3346,3356,3366,3376,3385,3395,3405,3415,3424,3434,3443,3452,3462,3471,3480,3490,3499,3508,3517,3526,3535,3544,3552,3561,3570,3578,3587,3595,3604,3612,3620,3629,3637,3645,3653,3661,3669,3677,3684,3692,3700,3707,3715,3722,3730,3737,3744,3752,3759,3766,3773,3780,3786,3793,3800,3807,3813,3820,3826,3832,3839,3845,3851,3857,3863,3869,3875,3881,3886,3892,3898,3903,3909,3914,3919,3924,3929,3934,3939,3944,3949,3954,3959,3963,3968,3972,3976,3981,3985,3989,3993,3997,4001,4005,4009,4012,4016,4019,4023,4026,4029,4033,4036,4039,4042,4045,4047,4050,4053,4055,4058,4060,4063,4065,4067,4069,4071,4073,4075,4077,4078,4080,4081,4083,4084,4086,4087,4088,4089,4090,4091,4092,4092,4093,4093,4094,4094,4095,4095,4095,4095,4095,4095,4095,4094,4094,4094,4093,4093,4092,4091,4090,4089,4088,4087,4086,4085,4084,4082,4081,4079,4078,4076,4074,4072,4070,4068,4066,4064,4061,4059,4057,4054,4052,4049,4046,4043,4040,4037,4034,4031,4028,4025,4021,4018,4014,4010,4007,4003,3999,3995,3991,3987,3983,3979,3974,3970,3965,3961,3956,3952,3947,3942,3937,3932,3927,3922,3916,3911,3906,3900,3895,3889,3884,3878,3872,3866,3860,3854,3848,3842,3836,3829,3823,3816,3810,3803,3797,3790,3783,3776,3769,3762,3755,3748,3741,3733,3726,3719,3711,3704,3696,3688,3681,3673,3665,3657,3649,3641,3633,3624,3616,3608,3599,3591,3583,3574,3565,3557,3548,3539,3530,3521,3512,3503,3494,3485,3476,3467,3457,3448,3438,3429,3419,3410,3400,3390,3381,3371,3361,3351,3341,3331,3321,3311,3301,3290,3280,3270,3259,3249,3238,3228,3217,3207,3196,3185,3175,3164,3153,3142,3131,3120,3109,3098,3087,3076,3065,3054,3042,3031,3020,3008,2997,2985,2974,2962,2951,2939,2928,2916,2904,2892,2881,2869,2857,2845,2833,2821,2809,2797,2785,2773,2761,2749,2737,2725,2713,2700,2688,2676,2664,2651,2639,2627,2614,2602,2589,2577,2564,2552,2539,2527,2514,2502,2489,2477,2464,2451,2439,2426,2413,2401,2388,2375,2362,2350,2337,2324,2311,2298,2286,2273,2260,2247,2234,2221,2209,2196,2183,2170,2157,2144,2131,2118,2106,2093,2080,2067,2054,2041,2028,2015,2002,1989,1977,1964,1951,1938,1925,1912,1899,1886,1874,1861,1848,1835,1822,1809,1797,1784,1771,1758,1745,1733,1720,1707,1694,1682,1669,1656,1644,1631,1618,1606,1593,1581,1568,1556,1543,1531,1518,1506,1493,1481,1468,1456,1444,1431,1419,1407,1395,1382,1370,1358,1346,1334,1322,1310,1298,1286,1274,1262,1250,1238,1226,1214,1203,1191,1179,1167,1156,1144,1133,1121,1110,1098,1087,1075,1064,1053,1041,1030,1019,1008,997,986,975,964,953,942,931,920,910,899,888,878,867,857,846,836,825,815,805,794,784,774,764,754,744,734,724,714,705,695,685,676,666,657,647,638,628,619,610,601,592,583,574,565,556,547,538,530,521,512,504,496,487,479,471,462,454,446,438,430,422,414,407,399,391,384,376,369,362,354,347,340,333,326,319,312,305,298,292,285,279,272,266,259,253,247,241,235,229,223,217,211,206,200,195,189,184,179,173,168,163,158,153,148,143,139,134,130,125,121,116,112,108,104,100,96,92,88,85,81,77,74,70,67,64,61,58,55,52,49,46,43,41,38,36,34,31,29,27,25,23,21,19,17,16,14,13,11,10,9,8,7,6,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,2,2,3,3,4,5,6,7,8,9,11,12,14,15,17,18,20,22,24,26,28,30,32,35,37,40,42,45,48,50,53,56,59,62,66,69,72,76,79,83,86,90,94,98,102,106,110,114,119,123,127,132,136,141,146,151,156,161,166,171,176,181,186,192,197,203,209,214,220,226,232,238,244,250,256,263,269,275,282,288,295,302,309,315,322,329,336,343,351,358,365,373,380,388,395,403,411,418,426,434,442,450,458,466,475,483,491,500,508,517,525,534,543,551,560,569,578,587,596,605,615,624,633,643,652,661,671,680,690,700,710,719,729,739,749,759,769,779,789,800,810,820,830,841,851,862,872,883,894,904,915,926,937,947,958,969,980,991,1002,1014,1025,1036,1047,1058,1070,1081,1092,1104,1115,1127,1138,1150,1162,1173,1185,1197,1208,1220,1232,1244,1256,1268,1280,1292,1304,1316,1328,1340,1352,1364,1376,1388,1401,1413,1425,1438,1450,1462,1475,1487,1499,1512,1524,1537,1549,1562,1574,1587,1600,1612,1625,1637,1650,1663,1675,1688,1701,1714,1726,1739,1752,1765,1777,1790,1803,1816,1829,1841,1854,1867,1880,1893,1906,1919,1931,1944,1957,1970,1983,1996,2009,2022,2035};
|
||||
|
||||
uint32_t passed_time = 0;
|
||||
int FM_factor;
|
||||
uint32_t sig_period_us = 945; // the period of the signal in microseconds
|
||||
uint32_t timer = 0;
|
||||
|
||||
void loop() {
|
||||
// Read the message signal and map it to a value from 90 to -90 us.
|
||||
// 90 microseconds corresponds to half of 22 kHz (an audio input signal).
|
||||
FM_factor = fastAnalogRead(ADC_CHANNEL_0);
|
||||
FM_factor = map(FM_factor, 0, 4095, 100, -100);
|
||||
//modulate the carrier signal with the message signal by changing the reset value of the timer
|
||||
// TC_SetRC(TC2, 0, 997 + FM_factor);
|
||||
sig_period_us = 945 + FM_factor;
|
||||
|
||||
// read in the current timer value
|
||||
// timer_val = TC_ReadCV(TC2, 0);
|
||||
passed_time += TC_ReadCV(TC2, 0) - timer;
|
||||
timer = TC_ReadCV(TC2, 0);
|
||||
while(passed_time > sig_period_us) {
|
||||
passed_time -= sig_period_us;
|
||||
}
|
||||
|
||||
// map the timer value to a value from 0-997
|
||||
int phase = map(passed_time, 0, 997 + FM_factor, 0, 997);
|
||||
|
||||
// write the FM signal to the DAC
|
||||
dacc_write_conversion_data(DACC, sine_wave[phase]);
|
||||
|
||||
}
|
||||
11
test/README
Normal file
11
test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||
Reference in New Issue
Block a user