William Decker
/
FM_Transmitter
Using the NS73M
main.cpp@0:ab6014cc9c12, 2013-03-04 (annotated)
- Committer:
- whdecker
- Date:
- Mon Mar 04 20:44:00 2013 +0000
- Revision:
- 0:ab6014cc9c12
First FM transmitter release (NS73M)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
whdecker | 0:ab6014cc9c12 | 1 | // Experimentally derived Band Settings for VFO ... |
whdecker | 0:ab6014cc9c12 | 2 | // Band 0: 83.78 - 91.72 |
whdecker | 0:ab6014cc9c12 | 3 | // Band 1: 88.74 - 98.28 |
whdecker | 0:ab6014cc9c12 | 4 | // Band 2: 93.10 - 104.00 |
whdecker | 0:ab6014cc9c12 | 5 | // Band 3: 99.50 - 112.72 |
whdecker | 0:ab6014cc9c12 | 6 | // ref: http://cba.sakura.ne.jp/sub04/jisaku36.htm (translated) |
whdecker | 0:ab6014cc9c12 | 7 | |
whdecker | 0:ab6014cc9c12 | 8 | #include "mbed.h" |
whdecker | 0:ab6014cc9c12 | 9 | #include "TextLCD.h" |
whdecker | 0:ab6014cc9c12 | 10 | |
whdecker | 0:ab6014cc9c12 | 11 | #define topFM 107900000 // Top of the FM Dial Range in USA |
whdecker | 0:ab6014cc9c12 | 12 | #define botFM 87500000 // Bottom of the FM Dial Range in USA |
whdecker | 0:ab6014cc9c12 | 13 | #define incrFM 200000 // FM Channel Increment in USA |
whdecker | 0:ab6014cc9c12 | 14 | |
whdecker | 0:ab6014cc9c12 | 15 | long frequency = 97300000; // the default initial frequency in Hz |
whdecker | 0:ab6014cc9c12 | 16 | long newFrequency = 0; |
whdecker | 0:ab6014cc9c12 | 17 | bool mute = true; |
whdecker | 0:ab6014cc9c12 | 18 | |
whdecker | 0:ab6014cc9c12 | 19 | LocalFileSystem local("local"); |
whdecker | 0:ab6014cc9c12 | 20 | TextLCD lcd(p15, p16, p17, p18, p19, p20); // rs, e, d4-d7 |
whdecker | 0:ab6014cc9c12 | 21 | Serial pc(USBTX, USBRX); |
whdecker | 0:ab6014cc9c12 | 22 | I2C i2c(p9, p10); |
whdecker | 0:ab6014cc9c12 | 23 | DigitalIn left(p23); |
whdecker | 0:ab6014cc9c12 | 24 | DigitalIn center(p22); |
whdecker | 0:ab6014cc9c12 | 25 | DigitalIn right(p21); |
whdecker | 0:ab6014cc9c12 | 26 | FILE *fp; |
whdecker | 0:ab6014cc9c12 | 27 | |
whdecker | 0:ab6014cc9c12 | 28 | float storedF = 10.1; |
whdecker | 0:ab6014cc9c12 | 29 | |
whdecker | 0:ab6014cc9c12 | 30 | const int addr= 0xCC; |
whdecker | 0:ab6014cc9c12 | 31 | |
whdecker | 0:ab6014cc9c12 | 32 | void writeToReg(unsigned int, unsigned int, unsigned int); |
whdecker | 0:ab6014cc9c12 | 33 | void initializeTransmitter(long); |
whdecker | 0:ab6014cc9c12 | 34 | void setFrequency(long); |
whdecker | 0:ab6014cc9c12 | 35 | |
whdecker | 0:ab6014cc9c12 | 36 | int main() { |
whdecker | 0:ab6014cc9c12 | 37 | lcd.printf("Starting up.\r\n"); |
whdecker | 0:ab6014cc9c12 | 38 | left.mode(PullUp); |
whdecker | 0:ab6014cc9c12 | 39 | center.mode(PullUp); |
whdecker | 0:ab6014cc9c12 | 40 | right.mode(PullUp); |
whdecker | 0:ab6014cc9c12 | 41 | wait_ms(100); //Wait for VDD to settle |
whdecker | 0:ab6014cc9c12 | 42 | |
whdecker | 0:ab6014cc9c12 | 43 | fp = fopen("/local/out.txt", "r"); |
whdecker | 0:ab6014cc9c12 | 44 | fscanf(fp, "%f", &storedF); |
whdecker | 0:ab6014cc9c12 | 45 | fclose(fp); |
whdecker | 0:ab6014cc9c12 | 46 | |
whdecker | 0:ab6014cc9c12 | 47 | frequency = ((long)(storedF*100.0))*10000; |
whdecker | 0:ab6014cc9c12 | 48 | |
whdecker | 0:ab6014cc9c12 | 49 | //lcd.cls(); |
whdecker | 0:ab6014cc9c12 | 50 | //lcd.printf("Transmitting on FM %d", frequency); |
whdecker | 0:ab6014cc9c12 | 51 | |
whdecker | 0:ab6014cc9c12 | 52 | initializeTransmitter(frequency); |
whdecker | 0:ab6014cc9c12 | 53 | |
whdecker | 0:ab6014cc9c12 | 54 | while(1) { |
whdecker | 0:ab6014cc9c12 | 55 | if(left == 0) |
whdecker | 0:ab6014cc9c12 | 56 | { |
whdecker | 0:ab6014cc9c12 | 57 | if(frequency - incrFM > botFM) |
whdecker | 0:ab6014cc9c12 | 58 | frequency = frequency - incrFM; |
whdecker | 0:ab6014cc9c12 | 59 | else |
whdecker | 0:ab6014cc9c12 | 60 | frequency = topFM; |
whdecker | 0:ab6014cc9c12 | 61 | |
whdecker | 0:ab6014cc9c12 | 62 | lcd.cls(); |
whdecker | 0:ab6014cc9c12 | 63 | setFrequency(frequency); |
whdecker | 0:ab6014cc9c12 | 64 | lcd.printf("Transmitting on FM %2.1f", float(frequency)/1000000.0); |
whdecker | 0:ab6014cc9c12 | 65 | |
whdecker | 0:ab6014cc9c12 | 66 | fp = fopen("/local/out.txt", "w"); // Open "out.txt" on the local file system for writing |
whdecker | 0:ab6014cc9c12 | 67 | fprintf(fp, "%2.1f", float(frequency)/1000000.0); |
whdecker | 0:ab6014cc9c12 | 68 | fclose(fp); |
whdecker | 0:ab6014cc9c12 | 69 | } |
whdecker | 0:ab6014cc9c12 | 70 | else if (right == 0) |
whdecker | 0:ab6014cc9c12 | 71 | { |
whdecker | 0:ab6014cc9c12 | 72 | if(frequency + incrFM < topFM) |
whdecker | 0:ab6014cc9c12 | 73 | frequency = frequency + incrFM; |
whdecker | 0:ab6014cc9c12 | 74 | else |
whdecker | 0:ab6014cc9c12 | 75 | frequency = botFM; |
whdecker | 0:ab6014cc9c12 | 76 | |
whdecker | 0:ab6014cc9c12 | 77 | lcd.cls(); |
whdecker | 0:ab6014cc9c12 | 78 | setFrequency(frequency); |
whdecker | 0:ab6014cc9c12 | 79 | lcd.printf("Transmitting on FM %2.1f", float(frequency)/1000000.0); |
whdecker | 0:ab6014cc9c12 | 80 | |
whdecker | 0:ab6014cc9c12 | 81 | fp = fopen("/local/out.txt", "w"); // Open "out.txt" on the local file system for writing |
whdecker | 0:ab6014cc9c12 | 82 | fprintf(fp, "%2.1f", float(frequency)/1000000.0); |
whdecker | 0:ab6014cc9c12 | 83 | fclose(fp); |
whdecker | 0:ab6014cc9c12 | 84 | } |
whdecker | 0:ab6014cc9c12 | 85 | else if (center == 0) |
whdecker | 0:ab6014cc9c12 | 86 | { |
whdecker | 0:ab6014cc9c12 | 87 | frequency = 97300000; |
whdecker | 0:ab6014cc9c12 | 88 | lcd.cls(); |
whdecker | 0:ab6014cc9c12 | 89 | setFrequency(frequency); |
whdecker | 0:ab6014cc9c12 | 90 | lcd.printf("Transmitting on FM %2.1f", float(frequency)/1000000.0); |
whdecker | 0:ab6014cc9c12 | 91 | |
whdecker | 0:ab6014cc9c12 | 92 | fp = fopen("/local/out.txt", "w"); // Open "out.txt" on the local file system for writing |
whdecker | 0:ab6014cc9c12 | 93 | fprintf(fp, "%2.1f", float(frequency)/1000000.0); |
whdecker | 0:ab6014cc9c12 | 94 | fclose(fp); |
whdecker | 0:ab6014cc9c12 | 95 | } |
whdecker | 0:ab6014cc9c12 | 96 | wait_ms(200); // lazy debounce |
whdecker | 0:ab6014cc9c12 | 97 | } |
whdecker | 0:ab6014cc9c12 | 98 | } |
whdecker | 0:ab6014cc9c12 | 99 | |
whdecker | 0:ab6014cc9c12 | 100 | void initializeTransmitter(long freq) |
whdecker | 0:ab6014cc9c12 | 101 | { |
whdecker | 0:ab6014cc9c12 | 102 | lcd.printf("Initializing..."); |
whdecker | 0:ab6014cc9c12 | 103 | |
whdecker | 0:ab6014cc9c12 | 104 | writeToReg(addr, 0x0E, 0x05); // Software reset |
whdecker | 0:ab6014cc9c12 | 105 | |
whdecker | 0:ab6014cc9c12 | 106 | writeToReg(addr, 0x01, 0xB4); // Reg 1: forced subccarrier, pilot tone on |
whdecker | 0:ab6014cc9c12 | 107 | |
whdecker | 0:ab6014cc9c12 | 108 | writeToReg(addr, 0x02, 0x03); // Reg 2: Unlock detect off, 2mW Tx Power |
whdecker | 0:ab6014cc9c12 | 109 | |
whdecker | 0:ab6014cc9c12 | 110 | setFrequency(freq); |
whdecker | 0:ab6014cc9c12 | 111 | |
whdecker | 0:ab6014cc9c12 | 112 | //writeToReg(addr, 0x08, 0x1A); //Register 8: set Osc on band 2 |
whdecker | 0:ab6014cc9c12 | 113 | |
whdecker | 0:ab6014cc9c12 | 114 | writeToReg(addr, 0x00, 0xA1); //Register 0: 200mV audio input, 75us pre-emphasis on, crystal off, power on |
whdecker | 0:ab6014cc9c12 | 115 | |
whdecker | 0:ab6014cc9c12 | 116 | writeToReg(addr, 0x0E, 0x05); // Software reset |
whdecker | 0:ab6014cc9c12 | 117 | |
whdecker | 0:ab6014cc9c12 | 118 | writeToReg(addr, 0x06, 0x1E); // Reg 6: chare pumps at 320uA and 80 uA |
whdecker | 0:ab6014cc9c12 | 119 | |
whdecker | 0:ab6014cc9c12 | 120 | lcd.cls(); |
whdecker | 0:ab6014cc9c12 | 121 | lcd.printf("Transmitting on FM %2.1f", float(freq)/1000000.0); //for debugging |
whdecker | 0:ab6014cc9c12 | 122 | } |
whdecker | 0:ab6014cc9c12 | 123 | |
whdecker | 0:ab6014cc9c12 | 124 | void setFrequency(long freq) |
whdecker | 0:ab6014cc9c12 | 125 | { |
whdecker | 0:ab6014cc9c12 | 126 | int new_frequency; |
whdecker | 0:ab6014cc9c12 | 127 | |
whdecker | 0:ab6014cc9c12 | 128 | // New Range Checking... Implement the (experimentally determined) VFO bands: |
whdecker | 0:ab6014cc9c12 | 129 | if (freq < 88500000) { // Band 3 |
whdecker | 0:ab6014cc9c12 | 130 | writeToReg(addr, 0x08, 0x1B); |
whdecker | 0:ab6014cc9c12 | 131 | //Serial.println("Band 3"); |
whdecker | 0:ab6014cc9c12 | 132 | } |
whdecker | 0:ab6014cc9c12 | 133 | else if (freq < 97900000) { // Band 2 |
whdecker | 0:ab6014cc9c12 | 134 | writeToReg(addr, 0x08, 0x1A); |
whdecker | 0:ab6014cc9c12 | 135 | //Serial.println("Band 2"); |
whdecker | 0:ab6014cc9c12 | 136 | } |
whdecker | 0:ab6014cc9c12 | 137 | else if (freq < 103000000) { // Band 1 |
whdecker | 0:ab6014cc9c12 | 138 | writeToReg(addr, 0x08, 0x19); |
whdecker | 0:ab6014cc9c12 | 139 | //Serial.println("Band 1"); |
whdecker | 0:ab6014cc9c12 | 140 | } |
whdecker | 0:ab6014cc9c12 | 141 | else { // Band 0 |
whdecker | 0:ab6014cc9c12 | 142 | // Must be OVER 103.000.000, |
whdecker | 0:ab6014cc9c12 | 143 | writeToReg(addr, 0x08, 0x18); |
whdecker | 0:ab6014cc9c12 | 144 | //Serial.println("Band 0"); |
whdecker | 0:ab6014cc9c12 | 145 | } |
whdecker | 0:ab6014cc9c12 | 146 | |
whdecker | 0:ab6014cc9c12 | 147 | new_frequency = (freq + 304000) / 8192; |
whdecker | 0:ab6014cc9c12 | 148 | |
whdecker | 0:ab6014cc9c12 | 149 | unsigned char reg3 = new_frequency & 255; //extract low byte of frequency register |
whdecker | 0:ab6014cc9c12 | 150 | unsigned char reg4 = new_frequency >> 8; //extract high byte of frequency register |
whdecker | 0:ab6014cc9c12 | 151 | writeToReg(addr, 0x03, reg3); //send low byte |
whdecker | 0:ab6014cc9c12 | 152 | writeToReg(addr, 0x04, reg4); //send high byte |
whdecker | 0:ab6014cc9c12 | 153 | |
whdecker | 0:ab6014cc9c12 | 154 | writeToReg(addr, 0x0E, 0x05); // Software reset |
whdecker | 0:ab6014cc9c12 | 155 | } |
whdecker | 0:ab6014cc9c12 | 156 | |
whdecker | 0:ab6014cc9c12 | 157 | void writeToReg(unsigned int addr, unsigned int reg, unsigned int data) |
whdecker | 0:ab6014cc9c12 | 158 | { |
whdecker | 0:ab6014cc9c12 | 159 | i2c.start(); |
whdecker | 0:ab6014cc9c12 | 160 | i2c.write(addr); |
whdecker | 0:ab6014cc9c12 | 161 | i2c.write(reg); |
whdecker | 0:ab6014cc9c12 | 162 | i2c.write(data); |
whdecker | 0:ab6014cc9c12 | 163 | i2c.stop(); |
whdecker | 0:ab6014cc9c12 | 164 | } |