├── OSSIADF7012Beacon ├── .ccsproject ├── .cproject ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.cdt.codan.core.prefs │ ├── org.eclipse.cdt.debug.core.prefs │ └── org.eclipse.core.resources.prefs ├── MSP430F2132.ccxml ├── aclkuart.c ├── aclkuart.h ├── adf7012.c ├── adf7012.h ├── gps.c ├── gps.h ├── i2c.c ├── i2c.h ├── lnk_msp430f2132.cmd ├── main.c ├── morse.c ├── morse.h ├── ossibeacon.h ├── ossitypes.h ├── printf.c ├── printf.h ├── system.c ├── system.h ├── util.c └── util.h ├── README.md ├── beacon └── main.c ├── comms └── main.c ├── lib ├── 24lc256.c ├── 24lc256.h ├── adc.c ├── adc.h ├── adf7020.c ├── adf7020.h ├── adf7021n.c ├── adf7021n.h ├── config.h ├── global.h ├── i2c.c ├── i2c.h ├── morse.c ├── morse.h ├── payload.h ├── pca9548a.c ├── pca9548a.h ├── tmp10x.c ├── tmp10x.h └── uart.c ├── obc ├── blink.c ├── i2c_payload.c ├── i2c_payload.h ├── main.c └── watchdog.c ├── payload └── main.c ├── test ├── LightScheduler.c ├── eeprom_test_ok.c ├── hardware.c ├── send.c └── tests.c ├── tmp10x.c └── tmp10x.h /OSSIADF7012Beacon/.ccsproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 100 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/.gitignore: -------------------------------------------------------------------------------- 1 | #Ignore Temporary Files# 2 | ################# 3 | *.?#? 4 | 5 | Debug/ 6 | Release/ -------------------------------------------------------------------------------- /OSSIADF7012Beacon/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | OSSIADF7012Beacon 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | 11 | 12 | ?name? 13 | 14 | 15 | 16 | org.eclipse.cdt.make.core.append_environment 17 | true 18 | 19 | 20 | org.eclipse.cdt.make.core.autoBuildTarget 21 | all 22 | 23 | 24 | org.eclipse.cdt.make.core.buildArguments 25 | -k 26 | 27 | 28 | org.eclipse.cdt.make.core.buildCommand 29 | ${CCS_UTILS_DIR}/bin/gmake 30 | 31 | 32 | org.eclipse.cdt.make.core.buildLocation 33 | ${BuildDirectory} 34 | 35 | 36 | org.eclipse.cdt.make.core.cleanBuildTarget 37 | clean 38 | 39 | 40 | org.eclipse.cdt.make.core.contents 41 | org.eclipse.cdt.make.core.activeConfigSettings 42 | 43 | 44 | org.eclipse.cdt.make.core.enableAutoBuild 45 | true 46 | 47 | 48 | org.eclipse.cdt.make.core.enableCleanBuild 49 | true 50 | 51 | 52 | org.eclipse.cdt.make.core.enableFullBuild 53 | true 54 | 55 | 56 | org.eclipse.cdt.make.core.fullBuildTarget 57 | all 58 | 59 | 60 | org.eclipse.cdt.make.core.stopOnError 61 | false 62 | 63 | 64 | org.eclipse.cdt.make.core.useDefaultBuildCmd 65 | true 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 71 | full,incremental, 72 | 73 | 74 | 75 | 76 | 77 | com.ti.ccstudio.core.ccsNature 78 | org.eclipse.cdt.core.cnature 79 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 80 | org.eclipse.cdt.core.ccnature 81 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 82 | 83 | 84 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/.settings/org.eclipse.cdt.codan.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Dec 16 15:57:07 KST 2012 2 | eclipse.preferences.version=1 3 | inEditor=false 4 | onBuild=false 5 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/.settings/org.eclipse.cdt.debug.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Dec 16 15:57:08 KST 2012 2 | eclipse.preferences.version=1 3 | org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker 4 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | #Fri Dec 21 17:18:54 KST 2012 2 | eclipse.preferences.version=1 3 | encoding//Debug/makefile=UTF-8 4 | encoding//Debug/objects.mk=UTF-8 5 | encoding//Debug/sources.mk=UTF-8 6 | encoding//Debug/subdir_rules.mk=UTF-8 7 | encoding//Debug/subdir_vars.mk=UTF-8 8 | encoding//Release/makefile=UTF-8 9 | encoding//Release/objects.mk=UTF-8 10 | encoding//Release/sources.mk=UTF-8 11 | encoding//Release/subdir_rules.mk=UTF-8 12 | encoding//Release/subdir_vars.mk=UTF-8 13 | encoding/adf7012.c=UTF-8 14 | encoding/main.c=UTF-8 15 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/MSP430F2132.ccxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/aclkuart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * aclkuart.c 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #include "aclkuart.h" 9 | static volatile uint8_t uart_rx_flag = 0; 10 | static volatile uint8_t rx_byte = '\0'; 11 | 12 | // Low-Frequency Baud Rate Mode 13 | // read chapter 15.3.10 of msp430x2xxx user's guide for baud rate generation 14 | void uart_setup_9600(void) 15 | { 16 | P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD, No need to set IO direction 17 | UCA0CTL1 |= UCSSEL_1; // CLK = ACLK 18 | UCA0BR0 = 0x03; // 3 = INT(3.41), 32.768kHz/9600 = 3.41 19 | UCA0BR1 = 0x00; // 20 | UCA0MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3 = round(0.41 * 8) 21 | UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** 22 | } 23 | 24 | void uart_setup_4800(void) 25 | { 26 | P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD, No need to set IO direction 27 | UCA0CTL1 |= UCSSEL_1; // CLK = ACLK 28 | UCA0BR0 = 0x06; // 6 = INT(6.83), 32.768kHz/4800 = 6.83 29 | UCA0BR1 = 0x00; // 30 | UCA0MCTL = UCBRS2 + UCBRS1 + UCBRS0; // Modulation UCBRSx = 7 = round(0.83 * 8) 31 | UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** 32 | } 33 | 34 | void uart_init(void) 35 | { 36 | IE2 |= UCA0RXIE; // default: Enable USCI_A0 RX interrupt 37 | IE2 &= ~UCA0TXIE; // default: Disable USCI_A0 TX interrupt 38 | } 39 | 40 | void i2c_set_rxFlag(void) 41 | { 42 | 43 | } 44 | 45 | void i2c_clear_rxFlag(void) 46 | { 47 | 48 | } 49 | 50 | uint8_t i2c_rx_ready(void) 51 | { 52 | return 0; 53 | } 54 | 55 | void uart_set_rxFlag(void) 56 | { 57 | uart_rx_flag = 1; 58 | } 59 | 60 | void uart_clear_rxFlag(void) 61 | { 62 | uart_rx_flag = 0; 63 | } 64 | 65 | uint8_t uart_rx_ready(void) 66 | { 67 | if(uart_rx_flag) 68 | { 69 | return 1; 70 | } 71 | else 72 | { 73 | return 0; 74 | } 75 | } 76 | 77 | uint8_t uart_get_byte(void) 78 | { 79 | // return only you have available data from uart, NOT i2c 80 | 81 | return rx_byte; 82 | } 83 | 84 | 85 | /** 86 | * Sends a single byte out through UART 87 | **/ 88 | void uart_send_byte(unsigned char byte) 89 | { 90 | 91 | while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? //TODO: change this to avoid infinite loop!!!!! 92 | UCA0TXBUF = byte; // TX -> RXed character 93 | 94 | } 95 | 96 | void puts(char *s) { 97 | char c; 98 | 99 | // Loops through each character in string 's' 100 | while (c = *s++) { 101 | uart_send_byte(c); 102 | } 103 | } 104 | /** 105 | * puts() is used by printf() to display or send a character. This function 106 | * determines where printf prints to. For this case it sends a character 107 | * out over UART. 108 | **/ 109 | void putc(unsigned b) { 110 | uart_send_byte(b); 111 | } 112 | 113 | 114 | // USCI A0/B0 Transmit ISR 115 | #pragma vector=USCIAB0TX_VECTOR 116 | __interrupt void USCI0TX_ISR(void) 117 | { 118 | IE2 &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt 119 | } 120 | 121 | // USCI A0/B0 Receive ISR 122 | #pragma vector=USCIAB0RX_VECTOR 123 | __interrupt void USCI0RX_ISR(void) 124 | { 125 | // TODO: I2C and UART handle at the same time 126 | rx_byte = UCA0RXBUF; // Get the received character 127 | 128 | // gps (uart) 129 | uart_set_rxFlag(); 130 | __bic_SR_register_on_exit(LPM3_bits); 131 | 132 | 133 | } 134 | 135 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/aclkuart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * aclkuart.h 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef ACLKUART_H_ 9 | #define ACLKUART_H_ 10 | 11 | #include "ossibeacon.h" 12 | 13 | void uart_setup_4800(void); 14 | void uart_setup_9600(void); 15 | void uart_init(void); 16 | 17 | void uart_set_rxFlag(void); 18 | void uart_clear_rxFlag(void); 19 | uint8_t uart_rx_ready(void); 20 | 21 | void i2c_set_rxFlag(void); 22 | void i2c_clear_rxFlag(void); 23 | uint8_t i2c_rx_ready(void); 24 | 25 | uint8_t uart_get_byte(void); 26 | 27 | void putc(unsigned); 28 | void puts(char *); 29 | 30 | 31 | 32 | 33 | #endif /* ACLKUART_H_ */ 34 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/adf7012.c: -------------------------------------------------------------------------------- 1 | /* 2 | * adf7012.c 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #include "adf7012.h" 9 | 10 | static volatile uint8_t vco_bias; 11 | static volatile uint8_t vco_adj; 12 | 13 | struct { 14 | struct { 15 | uint16_t frequency_error_correction; 16 | uint8_t r_divider; 17 | uint8_t crystal_doubler; 18 | uint8_t crystal_oscillator_disable; 19 | uint8_t clock_out_divider; 20 | uint8_t vco_adjust; 21 | uint8_t output_divider; 22 | } r0; 23 | 24 | struct { 25 | unsigned int fractional_n; 26 | uint8_t integer_n; 27 | uint8_t prescaler; 28 | } r1; 29 | 30 | struct { 31 | uint8_t mod_control; 32 | uint8_t gook; 33 | uint8_t power_amplifier_level; 34 | uint16_t modulation_deviation; 35 | uint8_t gfsk_modulation_control; 36 | uint8_t index_counter; 37 | } r2; 38 | 39 | struct { 40 | uint8_t pll_enable; 41 | uint8_t pa_enable; 42 | uint8_t clkout_enable; 43 | uint8_t data_invert; 44 | uint8_t charge_pump_current; 45 | uint8_t bleed_up; 46 | uint8_t bleed_down; 47 | uint8_t vco_disable; 48 | uint8_t muxout; 49 | uint8_t ld_precision; 50 | uint8_t vco_bias; 51 | uint8_t pa_bias; 52 | uint8_t pll_test_mode; 53 | uint8_t sd_test_mode; 54 | } r3; 55 | } adf_config; 56 | 57 | void ADF7012_setup(void) 58 | { 59 | // port init 60 | IO_DIRECTION(TXDATA, OUTPUT); 61 | //IO_DIRECTION(TXCLK, INPUT); // TODO: for GOOK modulation 62 | IO_DIRECTION(SCLK,OUTPUT); 63 | IO_DIRECTION(SDATA,OUTPUT); 64 | IO_DIRECTION(SLE,OUTPUT); 65 | IO_DIRECTION(CE,OUTPUT); 66 | IO_DIRECTION(PAON,OUTPUT); 67 | IO_DIRECTION(MUXOUT,INPUT); 68 | 69 | // default pin state 70 | IO_SET(PAON, LOW); 71 | IO_SET(TXDATA, LOW); 72 | IO_SET(SCLK, LOW); 73 | IO_SET(SDATA, LOW); 74 | IO_SET(SLE, LOW); 75 | IO_SET(CE, LOW); 76 | } 77 | 78 | void ADF7012_init(void) 79 | { 80 | // default pin state 81 | IO_SET(PAON, LOW); 82 | IO_SET(TXDATA, LOW); 83 | IO_SET(SCLK, LOW); 84 | IO_SET(SDATA, LOW); 85 | IO_SET(SLE, LOW); 86 | IO_SET(CE, LOW); 87 | 88 | // configure timer interrupt 89 | } 90 | 91 | void byte_write(unsigned char _register) 92 | { 93 | volatile int i; 94 | 95 | for(i = 7; i >= 0; i--) 96 | { 97 | IO_SET(SCLK, LOW); 98 | if(_register & (1<> 24-(i*8)) & 0xff; 126 | byte_write(_register); 127 | } 128 | // SLE 129 | __delay_cycles(10); 130 | IO_SET(SLE, HIGH); 131 | 132 | IO_SET(SDATA, LOW); // SDATA low 133 | //IO_SET(SLE, LOW); 134 | __delay_cycles(30); 135 | 136 | } 137 | 138 | 139 | void ADF7012_init_register_zero(void) { 140 | adf_config.r0.frequency_error_correction = 0; // Don't bother for now... 141 | adf_config.r0.r_divider = 5; // Whatever works best for 2m, 1.25m and 70 cm ham bands 142 | adf_config.r0.crystal_doubler = 0; // Who would want that? Lower f_pfd means finer channel steps. 143 | adf_config.r0.crystal_oscillator_disable = 0; // Disable internal crystal oscillator because we have an external VCXO 144 | adf_config.r0.clock_out_divider = 1; // Don't bother for now... 145 | adf_config.r0.vco_adjust = 0; // Don't bother for now... (Will be automatically adjusted until PLL lock is achieved) 146 | adf_config.r0.output_divider = ADF_OUTPUT_DIVIDER_BY_4; // Pre-set div 4 for 2m. Will be changed according tx frequency on the fly 147 | } 148 | 149 | void ADF7012_init_register_one(void) { 150 | adf_config.r1.integer_n = 37; // Pre-set for 144.390 MHz APRS. Will be changed according tx frequency on the fly 151 | adf_config.r1.fractional_n = 4074; // Pre-set for 144.390 MHz APRS. Will be changed according tx frequency on the fly 152 | adf_config.r1.prescaler = 0; // 8/9 requires an integer_n > 91; 4/5 only requires integer_n > 31 153 | } 154 | 155 | void ADF7012_init_register_two(void) { 156 | adf_config.r2.mod_control = ADF_MODULATION_OOK; // For AFSK the modulation is done through the external VCXO we don't want any FM generated by the ADF7012 itself 157 | adf_config.r2.gook = 0; // Whatever... This might give us a nicer swing in phase maybe... 158 | adf_config.r2.power_amplifier_level = 0; // Start PA power from 0. Output −20dBm at 0x0, and 13 dBm at 0x7E at 868 MHz 159 | 160 | adf_config.r2.modulation_deviation = 0; // 16 is about half maximum amplitude @ ASK. 161 | adf_config.r2.gfsk_modulation_control = 0; // Don't bother for now... 162 | adf_config.r2.index_counter = 0; // Don't bother for now... 163 | } 164 | 165 | void ADF7012_init_register_three(void) { 166 | adf_config.r3.pll_enable = 0; // Switch off PLL (will be switched on after Ureg is checked and confirmed ok) 167 | adf_config.r3.pa_enable = 0; // Switch off PA (will be switched on when PLL lock is confirmed) 168 | adf_config.r3.clkout_enable = 0; // No clock output needed at the moment 169 | adf_config.r3.data_invert = 0; // Results in a TX signal when TXDATA input is low 170 | adf_config.r3.charge_pump_current = ADF_CP_CURRENT_1_5; //ADF_CP_CURRENT_0_3; //ADF_CP_CURRENT_2_1; // 2.1 mA. This is the maximum 171 | adf_config.r3.bleed_up = 0; // Don't worry, be happy... 172 | adf_config.r3.bleed_down = 0; // Dito 173 | adf_config.r3.vco_disable = 0; // VCO is on 174 | 175 | adf_config.r3.muxout = ADF_MUXOUT_REG_READY; // Lights up the green LED if the ADF7012 is properly powered (changes to lock detection in a later stage) 176 | 177 | adf_config.r3.ld_precision = ADF_LD_PRECISION_5_CYCLES; // What the heck? It is recommended that LDP be set to 1; 0 is more relaxed 178 | adf_config.r3.vco_bias = 6; // In 0.5 mA steps; Default 6 means 3 mA; Maximum (15) is 8 mA 179 | adf_config.r3.pa_bias = 4; // In 1 mA steps; Default 4 means 8 mA; Minimum (0) is 5 mA; Maximum (7) is 12 mA (Datasheet says uA which is bullshit) 180 | adf_config.r3.pll_test_mode = 0; 181 | adf_config.r3.sd_test_mode = 0; 182 | } 183 | 184 | void ADF7012_init_all_registers(void) 185 | { 186 | ADF7012_init_register_zero(); 187 | ADF7012_init_register_one(); 188 | ADF7012_init_register_two(); 189 | ADF7012_init_register_three(); 190 | } 191 | 192 | void adf7012_write_register_zero(void) { 193 | 194 | uint32_t reg = 195 | (0) | 196 | ((uint32_t)(adf_config.r0.frequency_error_correction & 0x7FF) << 2) | 197 | ((uint32_t)(adf_config.r0.r_divider & 0xF ) << 13) | 198 | ((uint32_t)(adf_config.r0.crystal_doubler & 0x1 ) << 17) | 199 | ((uint32_t)(adf_config.r0.crystal_oscillator_disable & 0x1 ) << 18) | 200 | ((uint32_t)(adf_config.r0.clock_out_divider & 0xF ) << 19) | 201 | ((uint32_t)(adf_config.r0.vco_adjust & 0x3 ) << 23) | 202 | ((uint32_t)(adf_config.r0.output_divider & 0x3 ) << 25); 203 | 204 | ADF7012_regWrite(reg); 205 | } 206 | 207 | void adf7012_write_register_one(void) { 208 | uint32_t reg = 209 | (1) | 210 | ((uint32_t)(adf_config.r1.fractional_n & 0xFFF) << 2) | 211 | ((uint32_t)(adf_config.r1.integer_n & 0xFF ) << 14) | 212 | ((uint32_t)(adf_config.r1.prescaler & 0x1 ) << 22); 213 | 214 | ADF7012_regWrite(reg); 215 | } 216 | 217 | void adf7012_write_register_two(void) { 218 | uint32_t reg = 219 | (2) | 220 | ((uint32_t)(adf_config.r2.mod_control & 0x3 ) << 2) | 221 | ((uint32_t)(adf_config.r2.gook & 0x1 ) << 4) | 222 | ((uint32_t)(adf_config.r2.power_amplifier_level & 0x3F ) << 5) | 223 | ((uint32_t)(adf_config.r2.modulation_deviation & 0x1FF) << 11) | 224 | ((uint32_t)(adf_config.r2.gfsk_modulation_control & 0x7 ) << 20) | 225 | ((uint32_t)(adf_config.r2.index_counter & 0x3 ) << 23); 226 | 227 | ADF7012_regWrite(reg); 228 | } 229 | 230 | void adf7012_write_register_three(void) { 231 | uint32_t reg = 232 | (3) | 233 | ((uint32_t)(adf_config.r3.pll_enable & 0x1 ) << 2) | 234 | ((uint32_t)(adf_config.r3.pa_enable & 0x1 ) << 3) | 235 | ((uint32_t)(adf_config.r3.clkout_enable & 0x1 ) << 4) | 236 | ((uint32_t)(adf_config.r3.data_invert & 0x1 ) << 5) | 237 | ((uint32_t)(adf_config.r3.charge_pump_current & 0x3 ) << 6) | 238 | ((uint32_t)(adf_config.r3.bleed_up & 0x1 ) << 8) | 239 | ((uint32_t)(adf_config.r3.bleed_down & 0x1 ) << 9) | 240 | ((uint32_t)(adf_config.r3.vco_disable & 0x1 ) << 10) | 241 | ((uint32_t)(adf_config.r3.muxout & 0xF ) << 11) | 242 | ((uint32_t)(adf_config.r3.ld_precision & 0x1 ) << 15) | 243 | ((uint32_t)(adf_config.r3.vco_bias & 0xF ) << 16) | 244 | ((uint32_t)(adf_config.r3.pa_bias & 0x7 ) << 20) | 245 | ((uint32_t)(adf_config.r3.pll_test_mode & 0x1F ) << 23) | 246 | ((uint32_t)(adf_config.r3.sd_test_mode & 0xF ) << 28); 247 | 248 | ADF7012_regWrite(reg); 249 | } 250 | 251 | 252 | void ADF7012_enable(void) 253 | { 254 | IO_SET(CE, HIGH); 255 | __delay_cycles(10); 256 | } 257 | 258 | void ADF7012_disable(void) 259 | { 260 | IO_SET(CE, LOW); 261 | __delay_cycles(10); 262 | } 263 | 264 | void ADF7012_write_all_registers(void) 265 | { 266 | adf7012_write_register_zero(); 267 | adf7012_write_register_one(); 268 | adf7012_write_register_two(); 269 | adf7012_write_register_three(); 270 | } 271 | 272 | uint8_t ADF7012_isLocked(void) 273 | { 274 | if ((P1IN & BIT1) > 0) 275 | { 276 | return 1; 277 | } 278 | else 279 | { 280 | return 0; 281 | } 282 | } 283 | 284 | uint8_t ADF7012_isManyLocked(void) 285 | { 286 | volatile uint16_t cnt; 287 | volatile uint16_t i; 288 | cnt = 0; 289 | 290 | for(i = 0; i < 1000 ; i++) // sample PLL lock muxout for 1000 times 291 | { 292 | delay_ms(1); // total check time is 1000 * 1 ms = 1 sec 293 | if ((P1IN & BIT1) > 0) 294 | { 295 | cnt ++; 296 | } 297 | else 298 | { 299 | if(cnt > 0) // prevent overflow 300 | { 301 | cnt --; 302 | } 303 | } 304 | } 305 | 306 | if (cnt > 500) // if more than 500 times lock -> PLL Locked 307 | { 308 | printf("Lock Count %u\r\n",cnt); 309 | return 1; 310 | 311 | } 312 | else // if less than 500 times lock -> PLL not locked 313 | { 314 | printf("Lock Count %u\r\n",cnt); 315 | return 0; 316 | } 317 | } 318 | 319 | void ADF7012_set_VCO(uint8_t bias, uint8_t adj) 320 | { 321 | adf_config.r3.vco_bias = vco_bias = bias; 322 | adf_config.r0.vco_adjust = vco_adj = adj; 323 | 324 | } 325 | 326 | void ADF7012_set_PLL(uint8_t val) 327 | { 328 | adf_config.r3.pll_enable = val; 329 | } 330 | 331 | void ADF7012_set_PA(uint8_t val) 332 | { 333 | adf_config.r3.pa_enable = val; 334 | } 335 | 336 | void ADF7012_set_PALevel(uint8_t val) 337 | { 338 | min_max(0,63,val); 339 | adf_config.r2.power_amplifier_level = val; 340 | 341 | } 342 | 343 | 344 | void ADF7012_set_muxout(uint8_t val) 345 | { 346 | //ADF_MUXOUT_DIGITAL_LOCK = 4 347 | adf_config.r3.muxout = val; 348 | } 349 | 350 | uint8_t ADF7012_lock(void) 351 | { 352 | // fiddle around with bias and adjust capacity until the vco locks 353 | 354 | uint8_t adj = adf_config.r0.vco_adjust; // use default start values from setup 355 | uint8_t bias = adf_config.r3.vco_bias; // or the updated ones that worked last time 356 | volatile uint16_t i; 357 | 358 | adf_config.r3.pll_enable = 1; 359 | adf_config.r3.muxout = ADF_MUXOUT_DIGITAL_LOCK; 360 | ADF7012_enable(); 361 | ADF7012_write_all_registers(); 362 | delay_ms(50); 363 | ADF7012_isLocked(); 364 | 365 | while(!ADF7012_isLocked()) { 366 | 367 | // Serial.print("VCO not in lock. Trying adj: "); 368 | // Serial.print(adj); 369 | // Serial.print(" and bias: "); 370 | // Serial.println(bias); 371 | adf_config.r0.vco_adjust = adj; 372 | adf_config.r3.vco_bias = bias; 373 | adf_config.r3.muxout = ADF_MUXOUT_DIGITAL_LOCK; 374 | ADF7012_enable(); 375 | ADF7012_write_all_registers(); 376 | delay_ms(1); 377 | if(++bias == 14) { 378 | bias = 1; 379 | if(++adj == 4) { 380 | //Serial.println("Couldn't achieve PLL lock :( "); 381 | // Using best guess defaults: 382 | adf_config.r0.vco_adjust = 0; 383 | adf_config.r3.vco_bias = 5; 384 | 385 | return 0; 386 | } 387 | 388 | } 389 | 390 | delay_ms(1); 391 | } 392 | printf("PLL locked!\r\n"); 393 | printf("VCO Bias: %u\r\n",bias); 394 | printf("VCO adjust: %u\r\n",adj); 395 | 396 | ADF7012_set_VCO(bias,adj); 397 | return 1; 398 | } 399 | 400 | void ADF7012_findLock(void) 401 | { 402 | // fiddle around with bias and adjust capacity until the vco locks 403 | 404 | uint8_t adj = 0; 405 | uint8_t bias = 0; 406 | volatile uint16_t i; 407 | 408 | adf_config.r3.pll_enable = 1; 409 | adf_config.r3.muxout = ADF_MUXOUT_DIGITAL_LOCK; 410 | ADF7012_enable(); 411 | ADF7012_write_all_registers(); 412 | delay_ms(50); 413 | ADF7012_isLocked(); 414 | 415 | for (bias = 0 ; bias <15 ; bias++) 416 | { 417 | for (adj = 0; adj<5;adj++) 418 | { 419 | adf_config.r0.vco_adjust = adj; 420 | adf_config.r3.vco_bias = bias; 421 | adf_config.r3.muxout = ADF_MUXOUT_DIGITAL_LOCK; 422 | adf_config.r3.pa_enable = 0; 423 | ADF7012_enable(); 424 | ADF7012_write_all_registers(); 425 | delay_ms(300); 426 | 427 | if(ADF7012_isManyLocked()) 428 | { 429 | //resetExtWatchdogTimer(); 430 | printf("PLL locked!\r\n"); 431 | printf("VCO Bias: %u\r\n",bias); 432 | printf("VCO adjust: %u\r\n",adj); 433 | printf("\r\n"); 434 | adf_config.r3.pa_enable = 1; //ADF PA On 435 | ADF7012_enable(); 436 | ADF7012_write_all_registers(); 437 | IO_SET(TXDATA,HIGH); 438 | delay_ms(3000); 439 | IO_SET(TXDATA,LOW); 440 | adf_config.r3.pa_enable = 0; 441 | ADF7012_enable(); 442 | ADF7012_write_all_registers(); 443 | } 444 | else 445 | { 446 | printf("Not locked!\r\n"); 447 | printf("VCO Bias: %u\r\n",bias); 448 | printf("VCO adjust: %u\r\n",adj); 449 | printf("\r\n"); 450 | } 451 | } 452 | 453 | } 454 | 455 | } 456 | 457 | void ADF7012_findLockOnce(uint8_t bias,uint8_t adj) 458 | { 459 | volatile uint16_t i; 460 | 461 | adf_config.r3.pll_enable = 1; 462 | adf_config.r3.muxout = ADF_MUXOUT_DIGITAL_LOCK; 463 | ADF7012_enable(); 464 | ADF7012_write_all_registers(); 465 | delay_ms(50); 466 | ADF7012_isLocked(); 467 | 468 | adf_config.r0.vco_adjust = adj; 469 | adf_config.r3.vco_bias = bias; 470 | adf_config.r3.muxout = ADF_MUXOUT_DIGITAL_LOCK; 471 | adf_config.r3.pa_enable = 0; 472 | ADF7012_enable(); 473 | ADF7012_write_all_registers(); 474 | delay_ms(300); 475 | 476 | if(ADF7012_isManyLocked()) 477 | { 478 | //resetExtWatchdogTimer(); 479 | printf("PLL locked!\r\n"); 480 | printf("VCO Bias: %u\r\n",bias); 481 | printf("VCO adjust: %u\r\n",adj); 482 | printf("\r\n"); 483 | adf_config.r3.pa_enable = 1; //ADF PA On 484 | ADF7012_enable(); 485 | ADF7012_write_all_registers(); 486 | IO_SET(TXDATA,HIGH); 487 | delay_ms(3000); 488 | IO_SET(TXDATA,LOW); 489 | adf_config.r3.pa_enable = 0; 490 | ADF7012_enable(); 491 | ADF7012_write_all_registers(); 492 | } 493 | else 494 | { 495 | printf("Not locked!\r\n"); 496 | printf("VCO Bias: %u\r\n",bias); 497 | printf("VCO adjust: %u\r\n",adj); 498 | printf("\r\n"); 499 | } 500 | } 501 | 502 | 503 | void ADF7012_OOK(uint8_t val) 504 | { 505 | volatile uint8_t pa_level; 506 | if(val) 507 | { 508 | 509 | ADF7012_init_all_registers(); 510 | ADF7012_set_PLL(1); 511 | ADF7012_set_muxout(ADF_MUXOUT_DIGITAL_LOCK); 512 | ADF7012_set_VCO(vco_bias, vco_adj); // get VCO set values when PLL is locked from ADF7012_lock(); 513 | ADF7012_set_PALevel(63); 514 | ADF7012_set_PA(1); 515 | ADF7012_enable(); 516 | ADF7012_write_all_registers(); 517 | //TODO: increase PA level gradually and write update register value while TXDATA is HIGH from 0 to certain PA level 518 | IO_SET(TXDATA,HIGH); 519 | // for (pa_level = 0; pa_level < 64; pa_level++) // 63 is max PA level 520 | // { 521 | // ADF7012_set_PALevel(pa_level); 522 | // adf7012_write_register_two(); 523 | // } 524 | 525 | } 526 | else 527 | { 528 | IO_SET(TXDATA,LOW); 529 | // ADF7012_init_all_registers(); 530 | // for (pa_level = 63; pa_level > 0 ; pa_level--) // 63 is max PA level 531 | // { 532 | // ADF7012_set_PALevel(pa_level); 533 | // adf7012_write_register_two(); 534 | // } 535 | ADF7012_disable(); 536 | } 537 | } 538 | 539 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/adf7012.h: -------------------------------------------------------------------------------- 1 | /* 2 | * adf7012.h 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef ADF7012_H_ 9 | #define ADF7012_H_ 10 | 11 | #include "ossibeacon.h" 12 | #include "printf.h" 13 | 14 | // MSP430F2132 pin mapping 15 | #define TXDATA_PORT 1 16 | #define TXDATA_PIN 3 17 | 18 | #define TXCLK_PORT 1 19 | #define TXCLK_PIN 2 20 | 21 | #define SCLK_PORT 1 22 | #define SCLK_PIN 0 23 | 24 | #define SDATA_PORT 2 25 | #define SDATA_PIN 4 26 | 27 | #define SLE_PORT 2 28 | #define SLE_PIN 3 29 | 30 | #define CE_PORT 3 31 | #define CE_PIN 7 32 | 33 | #define MUXOUT_PORT 1 34 | #define MUXOUT_PIN 1 35 | 36 | #define PAON_PORT 3 37 | #define PAON_PIN 6 38 | 39 | // Register Constants ======================================================== 40 | 41 | // Register 0 ---------------------------------------------------------------- 42 | #define ADF_OUTPUT_DIVIDER_BY_1 0 43 | #define ADF_OUTPUT_DIVIDER_BY_2 1 44 | #define ADF_OUTPUT_DIVIDER_BY_4 2 45 | #define ADF_OUTPUT_DIVIDER_BY_8 3 46 | 47 | 48 | // Register 1 ---------------------------------------------------------------- 49 | #define ADF_PRESCALER_4_5 0 50 | #define ADF_PRESCALER_8_9 1 51 | #define ADF_PRESCALER ADF_PRESCALER_8_9 52 | 53 | // Register 2 ---------------------------------------------------------------- 54 | #define ADF_MODULATION_FSK 0 55 | #define ADF_MODULATION_GFSK 1 56 | #define ADF_MODULATION_ASK 2 57 | #define ADF_MODULATION_OOK 3 58 | 59 | // Register 3 ---------------------------------------------------------------- 60 | #define ADF_CP_CURRENT_0_3 0 61 | #define ADF_CP_CURRENT_0_9 1 62 | #define ADF_CP_CURRENT_1_5 2 63 | #define ADF_CP_CURRENT_2_1 3 64 | #define ADF_MUXOUT_LOGIC_LOW 0 65 | #define ADF_MUXOUT_LOGIC_HIGH 1 66 | #define ADF_MUXOUT_REG_READY 3 67 | #define ADF_MUXOUT_DIGITAL_LOCK 4 68 | #define ADF_MUXOUT_ANALOGUE_LOCK 5 69 | #define ADF_MUXOUT_R_DIVIDER_2 6 70 | #define ADF_MUXOUT_N_DIVIDER_2 7 71 | #define ADF_MUXOUT_RF_R_DIVIDER 8 72 | #define ADF_MUXOUT_DATA_RATE 9 73 | #define ADF_MUXOUT_BATT_2_35 10 74 | #define ADF_MUXOUT_BATT_2_75 11 75 | #define ADF_MUXOUT_BATT_3 12 76 | #define ADF_MUXOUT_BATT_3_25 13 77 | #define ADF_MUXOUT_TEST_MODE 14 78 | #define ADF_MUXOUT_SD_TEST_MODE 15 79 | #define ADF_LD_PRECISION_3_CYCLES 0 80 | #define ADF_LD_PRECISION_5_CYCLES 1 81 | 82 | void ADF7012_setup(void); 83 | void ADF7012_init(void); 84 | void ADF7012_init_all_registers(void); 85 | void ADF7012_write_all_registers(void); 86 | 87 | uint8_t ADF7012_lock(void); 88 | void ADF7012_findLock(void); 89 | 90 | void ADF7012_enable(void); 91 | void ADF7012_disable(void); 92 | 93 | void ADF7012_OOK(uint8_t val); 94 | 95 | 96 | 97 | #endif /* ADF7012_H_ */ 98 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/gps.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gps.c 3 | * 4 | * Created on: 2012. 12. 21. 5 | * Author: OSSI 6 | * Inspired by: http://rev0proto.com/wiki/index.php/Senior_Project / Justin Kenny 7 | */ 8 | 9 | #include "gps.h" 10 | 11 | static volatile uint8_t gps_ready_flag = 0; 12 | 13 | uint8_t rawgps[82]; 14 | uint8_t gpsgga[82]; 15 | uint8_t gpsindex = 0; 16 | uint8_t gpsdone = 0; 17 | Gps gpsdata = {"3518.5230", "12039.6090", "123456.789", "00", "000000.0", 'N', 'W', '0'}; 18 | 19 | uint8_t gps_array_data[100]={0}; // 59 = sizeof(gpsdata) + spacer character 20 | 21 | void gps_set_readyFlag(void) 22 | { 23 | gps_ready_flag = 1; 24 | } 25 | 26 | void gps_clear_readyFlag(void) 27 | { 28 | gps_ready_flag = 0; 29 | } 30 | 31 | uint8_t gps_is_ready(void) 32 | { 33 | if(gps_ready_flag) 34 | { 35 | return 1; 36 | } 37 | else 38 | { 39 | return 0; 40 | } 41 | 42 | } 43 | 44 | void gps_parse_nmea(void) 45 | { 46 | IE2 &= ~UCA0RXIE; //Disable receive interrupt 47 | uint8_t commas[MAXCOMMAS]; 48 | uint8_t i = 0, n; 49 | for(n=0;nMAXGPS;i++); //Find next comma; continue stepping through the array until we find 0x2C (,) 52 | commas[n] = i; //Store the index in commas[] array 53 | i++; 54 | } 55 | if(rawgps[commas[5]+1] != '0') //Make sure we have GPS fix; 0 = invalid 56 | { 57 | for(i=commas[1]+1;i = End of Transmission 212 | { 213 | gpsdone = 1; 214 | if(rawgps[4] == 'G') //Make sure this is a GGA sentence 215 | { 216 | gps_parse_nmea(); 217 | return 1; 218 | } 219 | } 220 | if(gpsdone != 1) 221 | { 222 | rawgps[gpsindex] = data; 223 | gpsindex++; 224 | } 225 | if(gpsindex > 81) 226 | { 227 | gpsindex = 0; 228 | } 229 | return 0; 230 | } 231 | 232 | uint8_t* gps_get_stream(void) 233 | { 234 | return gps_array_data; 235 | } 236 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/gps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * gps.h 3 | * 4 | * Created on: 2012. 12. 21. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef GPS_H_ 9 | #define GPS_H_ 10 | 11 | #include "ossibeacon.h" 12 | 13 | #define MAXCOMMAS 14 //Max commas to store positions of (14 for GGA sentence) 14 | #define MAXGPS 82 //Max NMEA string size 15 | #define MAXLAT 9 //Max latitude size in bytes 16 | #define MAXLONG 10 //Max longitude size in bytes 17 | #define MAXTIME 10 //Max time size in bytes 18 | #define MAXSATS 2 //Max sats size in bytes 19 | #define MAXALTI 8 //Max altitude size in bytes 20 | 21 | typedef struct 22 | { 23 | uint8_t lat[MAXLAT]; 24 | uint8_t lng[MAXLONG]; 25 | uint8_t time[MAXTIME]; 26 | uint8_t sats[MAXSATS]; 27 | uint8_t alti[MAXALTI]; 28 | uint8_t ns; 29 | uint8_t ew; 30 | uint8_t valid; 31 | } Gps; 32 | 33 | void gps_set_readyFlag(void); 34 | void gps_clear_readyFlag(void); 35 | uint8_t gps_is_ready(void); 36 | 37 | uint8_t gps_update_data(uint8_t data); 38 | void gps_make_packet(void); 39 | uint8_t* gps_get_stream(void); 40 | 41 | #endif /* GPS_H_ */ 42 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * i2c.c 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | #include "i2c.h" 8 | 9 | static volatile uint8_t i2c_rcv_flag; 10 | 11 | volatile uint8_t RXData; 12 | 13 | 14 | //void i2c_slave_init(void) 15 | //{ 16 | // // in slave mode, i2c can receive data even in LPM4 with ISR 17 | // i2c_rcv_flag = 0; 18 | // P3SEL |= 0x06; // Assign I2C pins to USCI_B0 19 | // UCB0CTL1 |= UCSWRST; // Enable SW reset 20 | // UCB0CTL0 = UCMODE_3 + UCSYNC; // I2C Slave, synchronous mode 21 | // UCB0I2COA = 0x48; // Own Address is 048h 22 | // UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation 23 | // IE2 |= UCB0RXIE; // Enable RX interrupt 24 | //} 25 | 26 | void i2c_set_readyFlag(void) 27 | { 28 | i2c_rcv_flag = 1; 29 | } 30 | 31 | void i2c_clear_readyFlag(void) 32 | { 33 | i2c_rcv_flag = 0; 34 | } 35 | 36 | uint8_t i2c_is_ready(void) 37 | { 38 | if(i2c_rcv_flag) 39 | { 40 | return 1; 41 | } 42 | else 43 | { 44 | return 0; 45 | } 46 | } 47 | 48 | uint8_t i2c_get_data() 49 | { 50 | return RXData; 51 | } 52 | 53 | // USCI_B0 Data ISR 54 | //#pragma vector = USCIAB0TX_VECTOR 55 | //__interrupt void USCIAB0TX_ISR(void) 56 | //{ 57 | // // TODO: I2C and UART handle at the same time 58 | // RXData = UCB0RXBUF; // Get RX data 59 | // __bic_SR_register_on_exit(LPM3_bits); // exits LPM3 60 | //} 61 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * i2c.h 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef I2C_H_ 9 | #define I2C_H_ 10 | 11 | #include "ossibeacon.h" 12 | 13 | void i2c_set_readyFlag(void); 14 | void i2c_clear_readyFlag(void); 15 | uint8_t i2c_is_ready(void); 16 | 17 | #endif /* I2C_H_ */ 18 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/lnk_msp430f2132.cmd: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | /* lnk_msp430f2132.cmd - LINKER COMMAND FILE FOR LINKING MSP430F2132 PROGRAMS */ 3 | /* */ 4 | /* Usage: lnk430 -o -m lnk.cmd */ 5 | /* cl430 -z -o -m lnk.cmd */ 6 | /* */ 7 | /*----------------------------------------------------------------------------*/ 8 | /* These linker options are for command line linking only. For IDE linking, */ 9 | /* you should set your linker options in Project Properties */ 10 | /* -c LINK USING C CONVENTIONS */ 11 | /* -stack 0x0100 SOFTWARE STACK SIZE */ 12 | /* -heap 0x0100 HEAP AREA SIZE */ 13 | /* */ 14 | /*----------------------------------------------------------------------------*/ 15 | 16 | 17 | /****************************************************************************/ 18 | /* SPECIFY THE SYSTEM MEMORY MAP */ 19 | /****************************************************************************/ 20 | 21 | MEMORY 22 | { 23 | SFR : origin = 0x0000, length = 0x0010 24 | PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 25 | PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 26 | RAM : origin = 0x0200, length = 0x0200 27 | INFOA : origin = 0x10C0, length = 0x0040 28 | INFOB : origin = 0x1080, length = 0x0040 29 | INFOC : origin = 0x1040, length = 0x0040 30 | INFOD : origin = 0x1000, length = 0x0040 31 | FLASH : origin = 0xE000, length = 0x1FDE 32 | INT00 : origin = 0xFFE0, length = 0x0002 33 | INT01 : origin = 0xFFE2, length = 0x0002 34 | INT02 : origin = 0xFFE4, length = 0x0002 35 | INT03 : origin = 0xFFE6, length = 0x0002 36 | INT04 : origin = 0xFFE8, length = 0x0002 37 | INT05 : origin = 0xFFEA, length = 0x0002 38 | INT06 : origin = 0xFFEC, length = 0x0002 39 | INT07 : origin = 0xFFEE, length = 0x0002 40 | INT08 : origin = 0xFFF0, length = 0x0002 41 | INT09 : origin = 0xFFF2, length = 0x0002 42 | INT10 : origin = 0xFFF4, length = 0x0002 43 | INT11 : origin = 0xFFF6, length = 0x0002 44 | INT12 : origin = 0xFFF8, length = 0x0002 45 | INT13 : origin = 0xFFFA, length = 0x0002 46 | INT14 : origin = 0xFFFC, length = 0x0002 47 | RESET : origin = 0xFFFE, length = 0x0002 48 | } 49 | 50 | /****************************************************************************/ 51 | /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ 52 | /****************************************************************************/ 53 | 54 | SECTIONS 55 | { 56 | .bss : {} > RAM /* GLOBAL & STATIC VARS */ 57 | .data : {} > RAM /* GLOBAL & STATIC VARS */ 58 | .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */ 59 | .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */ 60 | 61 | .text : {} > FLASH /* CODE */ 62 | .cinit : {} > FLASH /* INITIALIZATION TABLES */ 63 | .const : {} > FLASH /* CONSTANT DATA */ 64 | .cio : {} > RAM /* C I/O BUFFER */ 65 | 66 | .pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */ 67 | .init_array : {} > FLASH /* C++ CONSTRUCTOR TABLES */ 68 | .mspabi.exidx : {} > FLASH /* C++ CONSTRUCTOR TABLES */ 69 | .mspabi.extab : {} > FLASH /* C++ CONSTRUCTOR TABLES */ 70 | 71 | .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ 72 | .infoB : {} > INFOB 73 | .infoC : {} > INFOC 74 | .infoD : {} > INFOD 75 | 76 | /* MSP430 INTERRUPT VECTORS */ 77 | .int00 : {} > INT00 78 | .int01 : {} > INT01 79 | PORT1 : { * ( .int02 ) } > INT02 type = VECT_INIT 80 | PORT2 : { * ( .int03 ) } > INT03 type = VECT_INIT 81 | .int04 : {} > INT04 82 | ADC10 : { * ( .int05 ) } > INT05 type = VECT_INIT 83 | USCIAB0TX : { * ( .int06 ) } > INT06 type = VECT_INIT 84 | USCIAB0RX : { * ( .int07 ) } > INT07 type = VECT_INIT 85 | TIMER0_A1 : { * ( .int08 ) } > INT08 type = VECT_INIT 86 | TIMER0_A0 : { * ( .int09 ) } > INT09 type = VECT_INIT 87 | WDT : { * ( .int10 ) } > INT10 type = VECT_INIT 88 | COMPARATORA : { * ( .int11 ) } > INT11 type = VECT_INIT 89 | TIMER1_A1 : { * ( .int12 ) } > INT12 type = VECT_INIT 90 | TIMER1_A0 : { * ( .int13 ) } > INT13 type = VECT_INIT 91 | NMI : { * ( .int14 ) } > INT14 type = VECT_INIT 92 | .reset : {} > RESET /* MSP430 RESET VECTOR */ 93 | } 94 | 95 | /****************************************************************************/ 96 | /* INCLUDE PERIPHERALS MEMORY MAP */ 97 | /****************************************************************************/ 98 | 99 | -l msp430f2132.cmd 100 | 101 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | */ 4 | #include "ossibeacon.h" 5 | #include "printf.h" 6 | #include "adf7012.h" 7 | #include "aclkuart.h" 8 | #include "i2c.h" 9 | #include "morse.h" 10 | #include "gps.h" 11 | 12 | void beacon_data_receive(void); 13 | void beacon_data_processing(void); 14 | void beacon_data_send(void); 15 | 16 | void main(void) 17 | { 18 | //first thing to do 19 | int_wdt_disable(); 20 | clock_setup(); 21 | 22 | //ports setup 23 | IO_setup(); 24 | ext_wdt_setup(); 25 | uart_setup_9600(); 26 | ADF7012_setup(); 27 | 28 | //module init 29 | uart_init(); 30 | // TODO: check WDI timing 31 | ext_wdt_rst(); 32 | 33 | 34 | // wait 1000 ms in the beginning for stabilizing 32.768kHz 35 | // TODO:implement ACLK clock stability check -> 36 | delay_ms(1); 37 | 38 | while(1) 39 | { 40 | // Enter LPM3, interrupts enabled 41 | __bis_SR_register(LPM3_bits + GIE); 42 | beacon_data_receive(); 43 | beacon_data_processing(); 44 | beacon_data_send(); 45 | } 46 | } 47 | 48 | 49 | void beacon_data_receive(void) // uart related handler 50 | { 51 | // gps 52 | if (uart_rx_ready()) 53 | { 54 | uart_clear_rxFlag(); 55 | // uart_get_byte() only works after uart ISR 56 | // TODO:check possibility of error!!! 57 | if(gps_update_data(uart_get_byte())) 58 | { 59 | // if all the gps data we want are received 60 | gps_set_readyFlag(); 61 | return; 62 | } 63 | } 64 | else 65 | { 66 | return; 67 | } 68 | 69 | // i2c 70 | if (i2c_rx_ready()) 71 | { 72 | i2c_clear_rxFlag(); 73 | } 74 | } 75 | 76 | void beacon_data_processing(void) 77 | { 78 | //gps 79 | // gps 80 | if (gps_is_ready()) 81 | { 82 | gps_clear_readyFlag(); 83 | // process gps data 84 | // make packet from i2c and gps data 85 | 86 | gps_make_packet(); 87 | // ready to send morse code 88 | morse_init(20); 89 | } 90 | else 91 | { 92 | return; 93 | } 94 | 95 | 96 | // i2c 97 | if (i2c_is_ready()) 98 | { 99 | i2c_clear_readyFlag(); 100 | morse_init(12); 101 | 102 | } 103 | } 104 | 105 | void beacon_data_send(void) // timer0 related handler 106 | { 107 | if(morse_is_ready()) 108 | { 109 | // clear the flag 110 | morse_clear_sendFlag(); 111 | morse_send_bytes(gps_get_stream()); 112 | } 113 | else 114 | { 115 | return; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/morse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * morse.c 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #include "morse.h" 9 | 10 | 11 | // space . , 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 12 | const uint8_t code[39] ={0x00,0x15,0x33,0x1F,0x0F,0x07,0x03,0x01,0x00,0x10,0x18,0x1C,0x1E,0x01,0x08,0x0A,0x04,0x00,0x02,0x06,0x00,0x00,0x07,0x05,0x04,0x03,0x02,0x07,0x06,0x0D,0x02,0x00,0x01,0x01,0x01,0x03,0x09,0x0B,0x0C}; 13 | const uint8_t size[39] ={4,6,6,5,5,5,5,5,5,5,5,5,5,2,4,4,3,1,4,3,4,2,4,3,4,2,2,3,4,4,3,3,1,3,4,3,4,4,4}; 14 | 15 | static volatile uint8_t morse_send_flag = 0; 16 | 17 | static volatile uint16_t dot_length; 18 | static volatile uint16_t total_dot_length; 19 | static volatile uint16_t tick; 20 | 21 | static volatile uint16_t bytes_size = 0; 22 | 23 | void morse_timer_start(void) 24 | { 25 | // sending morse code 26 | 27 | // default: set to 12 WPM, 1 dot = 100 ms // 28 | // 1 WPM = 50 dots per min 29 | // ex) 1 WPM, 1 dot = 1200ms 30 | TA0CCR0 = 33; // 33 -> 1.007 ms 31 | TA0CTL = TASSEL_1 + MC_1; // ACLK, upmode 32 | tick = 0; 33 | TA0CCTL0 |= CCIE; // TA0CCR0 interrupt enabled 34 | } 35 | 36 | 37 | void morse_set_WPM(uint8_t wpm) 38 | { 39 | //min WPM = 1, 1 dot = 1200 ms 40 | //max WPM = 50, 1 dot = 24 ms 41 | //OSSI WPM = 12, 1 dot = 100 ms 42 | min_max(1,50,wpm); 43 | dot_length = (uint16_t)(1200 / wpm); 44 | } 45 | 46 | void morse_set_sendFlag(void) 47 | { 48 | morse_send_flag = 1; 49 | } 50 | 51 | void morse_clear_sendFlag(void) 52 | { 53 | morse_send_flag = 0; 54 | } 55 | 56 | uint8_t morse_is_ready(void) 57 | { 58 | if(morse_send_flag) 59 | { 60 | return 1; 61 | } 62 | else 63 | { 64 | return 0; 65 | } 66 | } 67 | 68 | uint16_t morse_set_dataSizeFrom(uint8_t * bytes) 69 | { 70 | volatile uint16_t bytes_size = 0; 71 | while(*bytes++) 72 | { 73 | bytes_size++; 74 | } 75 | 76 | return bytes_size; 77 | } 78 | 79 | void morse_init(uint8_t wpm) 80 | { 81 | // TODO: add extra initialization process if needed 82 | morse_set_WPM(wpm); 83 | ADF7012_init(); 84 | ADF7012_init_all_registers(); 85 | ADF7012_enable(); 86 | ADF7012_write_all_registers(); 87 | if(ADF7012_lock()) 88 | { 89 | morse_set_sendFlag(); 90 | ADF7012_disable(); 91 | return; 92 | } 93 | else 94 | { 95 | // TODO: do something when PLL is not locked!! 96 | // set vco bias and adj value with best guess for PLL 97 | morse_clear_sendFlag(); 98 | ADF7012_disable(); 99 | 100 | } 101 | } 102 | 103 | void morse_send_dots(uint8_t dots, uint8_t val) 104 | { 105 | total_dot_length = 0; 106 | total_dot_length = dots * dot_length; 107 | ADF7012_OOK(val); 108 | IO_SET(LED,val); 109 | morse_timer_start(); 110 | } 111 | 112 | void morse_send_bytes(uint8_t * bytes) 113 | { 114 | // TODO: check initialization of static variables 115 | static volatile uint16_t bytes_cnt =0; 116 | static volatile uint16_t dot_cnt =0; 117 | static volatile uint8_t dot_sent = 0; 118 | volatile uint16_t MAX_DATA_SIZE; 119 | 120 | MAX_DATA_SIZE = morse_set_dataSizeFrom(bytes); 121 | 122 | // size[bytes[bytes_cnt]-65]: number of dots to send including pause dots 123 | if( bytes_cnt < MAX_DATA_SIZE) 124 | { 125 | 126 | volatile uint8_t conv_index; 127 | 128 | //if Capital Alphabet letter 129 | if(bytes[bytes_cnt] >= 'A' && bytes[bytes_cnt] <= 'Z') 130 | { 131 | conv_index = 52; 132 | } 133 | 134 | //if numbers 135 | if(bytes[bytes_cnt] >= '0' && bytes[bytes_cnt] <= '9') 136 | { 137 | conv_index = 45; 138 | } 139 | 140 | //if Capital Alphabet letter 141 | if(bytes[bytes_cnt] == ',' ) 142 | { 143 | conv_index = 42; 144 | } 145 | 146 | //if Capital Alphabet letter 147 | if(bytes[bytes_cnt] == '.' ) 148 | { 149 | conv_index = 45; 150 | } 151 | 152 | if(bytes[bytes_cnt] == ' ' ) 153 | { 154 | dot_cnt = 0; 155 | bytes_cnt++; 156 | morse_send_dots(4,LOW); 157 | return; 158 | } 159 | 160 | volatile uint8_t total_dots = size[bytes[bytes_cnt]-conv_index]; 161 | volatile uint8_t converted = code[bytes[bytes_cnt]-conv_index]; 162 | 163 | if( dot_cnt < total_dots ) // count dots with pause added 164 | { 165 | if(dot_sent == 0) 166 | { 167 | dot_sent = 1; 168 | //check dash(1) or dot(0) from MSB 169 | if ((converted >> (total_dots - dot_cnt - 1)) & 0x01) 170 | { 171 | // 3 dots 172 | morse_send_dots(3,HIGH); 173 | return; 174 | } 175 | else 176 | { 177 | // 1 dot 178 | morse_send_dots(1,HIGH); 179 | return; 180 | } 181 | } 182 | 183 | if(dot_sent == 1) 184 | { 185 | dot_sent = 0; 186 | dot_cnt++; 187 | // if dots are sent 188 | // send 1 dot pause 189 | morse_send_dots(1,LOW); 190 | return; 191 | } 192 | } 193 | else // if a byte is sent 194 | { 195 | dot_cnt = 0; 196 | bytes_cnt++; 197 | morse_send_dots(2,LOW); // send 2 more dots so became total of 3 dots 198 | return; 199 | } 200 | } 201 | else // if all bytes are sent 202 | { 203 | dot_cnt = 0; 204 | bytes_cnt = 0; 205 | return; 206 | } 207 | 208 | } 209 | 210 | // Timer0_A0 interrupt service routine 211 | #pragma vector=TIMER0_A0_VECTOR 212 | __interrupt void Timer_A (void) 213 | { 214 | // data processing 215 | // increase tick 216 | // compare tick to dotCnt 217 | // data processing 218 | tick++; // every 1.007 ms 219 | 220 | if (tick > total_dot_length) 221 | { 222 | tick = 0; 223 | // morse_set_sendFlag(); 224 | morse_send_flag = 1; // replacing function call in ISR 225 | TA0CCTL0 &= ~CCIE; // disable timer interrupt 226 | // exit LPM3 227 | __bic_SR_register_on_exit(LPM3_bits); 228 | } 229 | 230 | 231 | } 232 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/morse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * morse.h 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef MORSE_H_ 9 | #define MORSE_H_ 10 | 11 | #include "ossibeacon.h" 12 | #include "adf7012.h" 13 | 14 | //#define MAX_DATA_SIZE 59 15 | 16 | void morse_set_sendFlag(void); 17 | void morse_clear_sendFlag(void); 18 | 19 | void morse_set_WPM(uint8_t wpm); 20 | 21 | void morse_init(uint8_t wpm); 22 | uint8_t morse_is_ready(void); 23 | void morse_send_bytes(uint8_t * bytes); 24 | 25 | #endif /* MORSE_H_ */ 26 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/ossibeacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ossibeacon.h 3 | * 4 | * Created on: 2012. 12. 22. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef OSSIBEACON_H_ 9 | #define OSSIBEACON_H_ 10 | 11 | #include "msp430x21x2.h" 12 | #include "system.h" 13 | #include "ossitypes.h" 14 | #include "util.h" 15 | 16 | 17 | 18 | #endif /* OSSIBEACON_H_ */ 19 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/ossitypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ossitypes.h 3 | * 4 | * Created on: 2012. 12. 22. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef OSSITYPES_H_ 9 | #define OSSITYPES_H_ 10 | 11 | typedef unsigned char uint8_t; 12 | typedef signed char int8_t; 13 | typedef unsigned short int uint16_t; 14 | typedef signed short int int16_t; 15 | typedef unsigned long int uint32_t; 16 | typedef signed long int int32_t; 17 | 18 | 19 | #endif /* OSSITYPES_H_ */ 20 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/printf.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Reusable MSP430 printf() 3 | * 4 | * Description: This printf function was written by oPossum and originally 5 | * posted on the 43oh.com forums. For more information on this 6 | * code, please see the link below. 7 | * 8 | * http://www.43oh.com/forum/viewtopic.php?f=10&t=1732 9 | * 10 | * A big thanks to oPossum for sharing such great code! 11 | * 12 | * Author: oPossum 13 | * Source: http://www.43oh.com/forum/viewtopic.php?f=10&t=1732 14 | * Date: 10-17-11 15 | * 16 | * Note: This comment section was written by Nicholas J. Conn on 06-07-2012 17 | * for use on NJC's MSP430 LaunchPad Blog. 18 | ******************************************************************************/ 19 | 20 | /* 21 | * printf.c 22 | * 23 | * Created on: 2012. 12. 19. 24 | * Author: OSSI 25 | */ 26 | 27 | 28 | #include "printf.h" 29 | 30 | 31 | 32 | static const unsigned long dv[] = { 33 | // 4294967296 // 32 bit unsigned max 34 | 1000000000,// +0 35 | 100000000, // +1 36 | 10000000, // +2 37 | 1000000, // +3 38 | 100000, // +4 39 | // 65535 // 16 bit unsigned max 40 | 10000, // +5 41 | 1000, // +6 42 | 100, // +7 43 | 10, // +8 44 | 1, // +9 45 | }; 46 | 47 | static void xtoa(unsigned long x, const unsigned long *dp) { 48 | char c; 49 | unsigned long d; 50 | if (x) { 51 | while (x < *dp) 52 | ++dp; 53 | do { 54 | d = *dp++; 55 | c = '0'; 56 | while (x >= d) 57 | ++c, x -= d; 58 | putc(c); 59 | } while (!(d & 1)); 60 | } else 61 | putc('0'); 62 | } 63 | 64 | static void puth(unsigned n) { 65 | static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', 66 | '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 67 | putc(hex[n & 15]); 68 | } 69 | 70 | void printf(char *format, ...) 71 | { 72 | char c; 73 | int i; 74 | long n; 75 | 76 | va_list a; 77 | va_start(a, format); 78 | while(c = *format++) { 79 | if(c == '%') { 80 | switch(c = *format++) { 81 | case 's': // String 82 | puts(va_arg(a, char*)); 83 | break; 84 | case 'c':// Char 85 | putc(va_arg(a, char)); 86 | break; 87 | case 'i':// 16 bit Integer 88 | case 'u':// 16 bit Unsigned 89 | i = va_arg(a, int); 90 | if(c == 'i' && i < 0) i = -i, putc('-'); 91 | xtoa((unsigned)i, dv + 5); 92 | break; 93 | case 'l':// 32 bit Long 94 | case 'n':// 32 bit uNsigned loNg 95 | n = va_arg(a, long); 96 | if(c == 'l' && n < 0) n = -n, putc('-'); 97 | xtoa((unsigned long)n, dv); 98 | break; 99 | case 'x':// 16 bit heXadecimal 100 | i = va_arg(a, int); 101 | puth(i >> 12); 102 | puth(i >> 8); 103 | puth(i >> 4); 104 | puth(i); 105 | break; 106 | case 0: return; 107 | default: goto bad_fmt; 108 | } 109 | } else 110 | bad_fmt: putc(c); 111 | } 112 | va_end(a); 113 | } 114 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/printf.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * printf.h 4 | * 5 | * Created on: 2012. 12. 19. 6 | * Author: OSSI 7 | */ 8 | 9 | #ifndef PRINTF_H_ 10 | #define PRINTF_H_ 11 | 12 | #include "stdarg.h" 13 | #include "aclkuart.h" 14 | 15 | void printf(char *, ...); 16 | 17 | #endif /* PRINTF_H_ */ 18 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/system.c: -------------------------------------------------------------------------------- 1 | /* 2 | * setup2132.c 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #include "system.h" 9 | 10 | 11 | void int_wdt_disable(void) 12 | { 13 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 14 | } 15 | 16 | void clock_setup(void) 17 | { 18 | // default: MCLK = SMCLK = DCO ~ 1.2MHz 19 | // set DCO speed to calibrated 1MHz 20 | BCSCTL1 = CALBC1_1MHZ; 21 | DCOCTL = CALDCO_1MHZ; 22 | } 23 | 24 | void IO_setup(void) 25 | { 26 | // general IO init 27 | // TODO: set unused pins!!! 28 | 29 | IO_DIRECTION(LED,OUTPUT); 30 | IO_SET(LED,LOW); 31 | 32 | } 33 | 34 | void ext_wdt_setup(void) 35 | { 36 | IO_DIRECTION(EXTWDT,OUTPUT); 37 | } 38 | 39 | void ext_wdt_rst(void) 40 | { 41 | //LOW-HIGH-LOW 42 | IO_SET(EXTWDT,LOW); 43 | delay_ms(1); 44 | IO_SET(EXTWDT,HIGH); 45 | delay_ms(1); 46 | IO_SET(EXTWDT,LOW); 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/system.h: -------------------------------------------------------------------------------- 1 | /* 2 | * setup2132.h 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #ifndef SETUP2132_H_ 9 | #define SETUP2132_H_ 10 | 11 | #include "msp430x21x2.h" 12 | #include "ossitypes.h" 13 | #include "util.h" 14 | 15 | // System IO Define 16 | #define LED_PORT 3 17 | #define LED_PIN 0 18 | 19 | #define EXTWDT_PORT 2 20 | #define EXTWDT_PIN 2 21 | 22 | void int_wdt_disable(void); 23 | void clock_setup(void); 24 | void IO_setup(void); 25 | void ext_wdt_setup(void); 26 | 27 | void ext_wdt_rst(void); 28 | 29 | #endif /* SETUP2132_H_ */ 30 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * util.c 3 | * 4 | * Created on: 2012. 12. 19. 5 | * Author: OSSI 6 | */ 7 | 8 | #include "util.h" 9 | 10 | void delay_ms(uint16_t delay) 11 | { 12 | volatile uint16_t i; 13 | for (i=0; i max) 26 | { 27 | value = max; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OSSIADF7012Beacon/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * global.h 3 | * 4 | * Created on: 2012. 6. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef GLOBAL_H_ 9 | #define GLOBAL_H_ 10 | 11 | #include "ossitypes.h" 12 | 13 | // Macros for turning on and off the LEDs (for testing only) 14 | enum {FALSE = 0, TRUE = 1}; 15 | #define _BV(bit) (1<<(bit)) 16 | 17 | //macros for IO config (with preprocessor abuse) 18 | #define st(x) do{x} while(__LINE__ == -1) 19 | 20 | enum IoState {LOW = 0, HIGH = 1, TOGGLE = 2}; 21 | #define IO_SET(name,val) _IO_SET(name##_PORT,name##_PIN,val) 22 | #define _IO_SET(port,pin,val) st(__IO_SET(port,pin,val);) 23 | #define __IO_SET(port,pin,val) if (val == TOGGLE)\ 24 | {\ 25 | st((P##port##OUT ^= _BV(pin)););\ 26 | }\ 27 | else if (val == HIGH)\ 28 | {\ 29 | st((P##port##OUT |= _BV(pin)););\ 30 | }\ 31 | else\ 32 | {\ 33 | st((P##port##OUT &= ~_BV(pin)););\ 34 | } 35 | 36 | enum IoDirection {INPUT = 0, OUTPUT = 1}; 37 | #define IO_DIRECTION(name,dir) _IO_DIRECTION(name##_PORT,name##_PIN,dir) 38 | 39 | #define _IO_DIRECTION(port,pin,dir) st(__IO_DIRECTION(port,pin,dir);) 40 | #define __IO_DIRECTION(port,pin,dir) if (dir)\ 41 | {\ 42 | st((P##port##DIR |= _BV(pin)););\ 43 | }\ 44 | else\ 45 | {\ 46 | st((P##port##DIR &= ~_BV(pin)););\ 47 | } 48 | 49 | void delay_ms(uint16_t delay); 50 | void min_max(uint8_t min, uint8_t max, uint8_t value); 51 | 52 | #endif /* GLOBAL_H_ */ 53 | 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ossicode/OSSI-1Firmware/1840b648c77d80e7563a8f0db944f8f300d14fa4/README.md -------------------------------------------------------------------------------- /beacon/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | .__ ____ 4 | ____ ______ ______|__| /_ | 5 | / _ \ / ___/ / ___/| | ______ | | 6 | ( <_> )\___ \ \___ \ | | /_____/ | | 7 | \____//____ >/____ >|__| |___| 8 | \/ \/ 9 | _ 10 | | | 11 | | |__ ___ __ _ ___ ___ _ __ 12 | | '_ \ / _ \ / _` | / __|/ _ \ | '_ \ 13 | | |_) || __/| (_| || (__| (_) || | | | 14 | |_.__/ \___| \__,_| \___|\___/ |_| |_| 15 | 16 | * Created on: 2012. 6. 3. 17 | * 18 | * 19 | */ 20 | 21 | #include 22 | #include "adf7020.h" 23 | #include "morse.h" 24 | 25 | #define PAON_PORT 2 26 | #define PAON_PIN 7 27 | 28 | char message[255] = {'o','s','s', 'i',' ','1',' ',' ',' ',' ',' ',' '}; 29 | int step = 10; 30 | 31 | void configure_clock() { 32 | BCSCTL1 |= RSEL0 + RSEL1 + RSEL2; 33 | DCOCTL = DCO0 + DCO1 + DCO2; // MAX 8MHZ 34 | BCSCTL2 |= SELM_0 + DIVM_0; 35 | } 36 | 37 | void Poweramp_On() { 38 | IO_DIRECTION(PAON, OUTPUT); 39 | IO_SET(PAON, HIGH); 40 | } 41 | 42 | int main(void) { 43 | volatile unsigned int i; 44 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 45 | P1DIR |= BIT1; // Set P1.0 to output direction 46 | // configure_clock(); 47 | // default 1MHZ? 48 | 49 | Poweramp_On(); 50 | 51 | ADF7020_1_Init(); 52 | ADF7020_1_SendStart(); 53 | 54 | while(1) 55 | adf7020_1_ook(1); 56 | 57 | // for(;;) { 58 | // for(i=0; i < step-1;i++ ) { 59 | // ascii(message[i]); 60 | // } 61 | // } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /comms/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "adf7021n.h" 3 | #include "morse.h" 4 | 5 | char message[255] = {'o','s','s', 'i',' ','1',' ',' ',' ',' ',' ',' '}; 6 | int step = 10; 7 | 8 | void configure_clock() { 9 | BCSCTL1 |= RSEL0 + RSEL1 + RSEL2; 10 | DCOCTL = DCO0 + DCO1 + DCO2; 11 | BCSCTL2 |= SELM_0 + DIVM_0; 12 | } 13 | 14 | int main(void) { 15 | volatile unsigned int i; 16 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 17 | configure_clock(); 18 | 19 | adf7021n_init(); 20 | // Ready to Send 21 | adf7021n_sendStart(); 22 | // Ready to Receive 23 | // adf7021n_recvStart(); 24 | _EINT(); 25 | 26 | while(1) { 27 | __delay_cycles(100000); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/24lc256.c: -------------------------------------------------------------------------------- 1 | #include "24lc256.h" 2 | #include "i2c.h" 3 | 4 | void EEPROM_Init(uint8_t slave_address) 5 | { 6 | _EINT(); 7 | InitI2C(slave_address); 8 | } 9 | 10 | /*---------------------------------------------------------------------------*/ 11 | void EEPROM_ByteWrite(unsigned int Address, unsigned char Data) 12 | // Description: 13 | // Byte Write Operation. The communication via the I2C bus with an EEPROM 14 | // (2465) is realized. A data byte is written into a user defined address. 15 | { 16 | unsigned char adr_hi; 17 | unsigned char adr_lo; 18 | 19 | // while (I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations 20 | while (I2CDCTL&I2CBB); //http://www.ti.com/lit/er/slaz018d/slaz018d.pdf 21 | 22 | adr_hi = Address >> 8; // calculate high byte 23 | adr_lo = Address & 0xFF; // and low byte of address 24 | 25 | I2CBuffer[2] = adr_hi; // store single bytes that have to be sent 26 | I2CBuffer[1] = adr_lo; // in the I2CBuffer. 27 | I2CBuffer[0] = Data; 28 | PtrTransmit = 2; // set I2CBuffer Pointer 29 | 30 | I2CWriteInit(); 31 | I2CNDAT = 3; // 1 control byte + 3 bytes should be transmitted 32 | I2CTCTL |= I2CSTT+I2CSTP; // start and stop condition generation 33 | // => I2C communication is started 34 | } 35 | 36 | void EEPROM_AckPolling(void) 37 | // Description: 38 | // Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is 39 | // in progress. It can be used to determine when a write cycle is completed. 40 | { 41 | unsigned int count; 42 | while (I2CDCTL&I2CBB); // wait until I2C module has finished all operations 43 | U0CTL &= ~I2CEN; // clear I2CEN bit => necessary to re-configure I2C module 44 | I2CTCTL |= I2CRM; // transmission is software controlled 45 | U0CTL |= I2CEN; // enable I2C module 46 | I2CIFG = NACKIFG; // set NACKIFG 47 | while (NACKIFG & I2CIFG) 48 | { 49 | I2CIFG=0x00; // clear I2C interrupt flags 50 | U0CTL |= MST; // define Master Mode 51 | I2CTCTL |= I2CTRX; // I2CTRX=1 => Transmit Mode (R/W bit = 0) 52 | 53 | _DINT(); // **** disable interrupts. following code lines should not be interrupted (time critical!!!) 54 | 55 | I2CTCTL |= I2CSTT; // start condition is generated 56 | while (I2CTCTL&I2CSTT); // wait till I2CSTT bit was cleared 57 | I2CTCTL |= I2CSTP; // stop condition is generated after slave address was sent 58 | // => I2C communication is started 59 | 60 | _EINT(); //**** enable interrupts again 61 | 62 | while (I2CDCTL&I2CBB); // wait till stop bit is reset 63 | } 64 | 65 | U0CTL &= ~I2CEN; // clear I2CEN bit => necessary to re-configure I2C module 66 | I2CTCTL &= ~I2CRM; // transmission is by the I2C module 67 | U0CTL |= I2CEN; // enable I2C module 68 | 69 | return; 70 | } 71 | 72 | unsigned char EEPROM_RandomRead(unsigned int Address) 73 | // Description: 74 | // Random Read Operation. Data is read from the EEPROM. The EEPROM 75 | // address is defined with the parameter Address. 76 | { 77 | unsigned char adr_hi; 78 | unsigned char adr_lo; 79 | 80 | while (I2CDCTL&I2CBB); //http://www.ti.com/lit/er/slaz018d/slaz018d.pdf 81 | 82 | adr_hi = Address >> 8; // calculate high byte 83 | adr_lo = Address & 0xFF; // and low byte of address 84 | 85 | I2CBuffer[1] = adr_hi; // store single bytes that have to be sent 86 | I2CBuffer[0] = adr_lo; // in the I2CBuffer. 87 | PtrTransmit = 1; // set I2CBuffer Pointer 88 | 89 | I2CWriteInit(); 90 | I2CNDAT = 2; // 1 control byte + 2 bytes should be transmitted 91 | I2CIFG &= ~ARDYIFG; // clear Access ready interrupt flag 92 | I2CTCTL |= I2CSTT; // start condition generation 93 | // => I2C communication is started 94 | while ((~I2CIFG)&ARDYIFG); // wait untill transmission is finished 95 | I2CReadInit(); 96 | I2CNDAT = 1; // 1 byte should be received 97 | PtrReceive = 0; 98 | 99 | I2CIFG &= ~ARDYIFG; // clear Access ready interrupt flag 100 | I2CTCTL |= I2CSTT+I2CSTP; // start receiving and finally generate 101 | // re-start and stop condition 102 | while ((~I2CIFG)&ARDYIFG); // wait untill transmission is finished 103 | return I2CBuffer[0]; 104 | } 105 | 106 | 107 | /*---------------------------------------------------------------------------*/ 108 | unsigned char EEPROM_CurrentAddressRead(void) 109 | // Description: 110 | // Current Address Read Operation. Data is read from the EEPROM. The current 111 | // address from the EEPROM is used. 112 | { 113 | // while (I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations 114 | while (I2CDCTL&I2CBB); //http://www.ti.com/lit/er/slaz018d/slaz018d.pdf 115 | 116 | I2CReadInit(); 117 | U0CTL |= MST; // define Master Mode 118 | I2CNDAT = 1; // 1 byte should be received 119 | I2CIFG &= ~ARDYIFG; // clear Access ready interrupt flag 120 | I2CTCTL |= I2CSTT+I2CSTP; // start receiving and finally generate 121 | // re-start and stop condition 122 | while ((~I2CIFG)&ARDYIFG); // wait untill transmission is finished 123 | return I2CBuffer[0]; 124 | } 125 | -------------------------------------------------------------------------------- /lib/24lc256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 24lc256.h 3 | * 4 | * Created on: 2012. 5. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef 24LC256_H_ 9 | #define 24LC256_H_ 10 | 11 | #include 12 | #include "i2c.h" 13 | #include "global.h" 14 | 15 | void EEPROM_ByteWrite(unsigned int Address, unsigned char Data); 16 | void EEPROM_AckPolling(); 17 | unsigned char EEPROM_RandomRead(unsigned int Address); 18 | unsigned char EEPROM_CurrentAddressRead(); 19 | void EEPROM_Init(uint8_t slave_address); 20 | 21 | 22 | #endif /* 24LC256_H_ */ 23 | -------------------------------------------------------------------------------- /lib/adc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * adc.c 3 | * Created on: 2012. 6. 3. 4 | * Author: donghee 5 | */ 6 | 7 | #include 8 | 9 | #include "global.h" 10 | #include "adc.h" 11 | 12 | 13 | void ADC_Init(void) 14 | { 15 | P6SEL |= (BIT0+BIT1); // P6.0 6.1 ADC option select 16 | 17 | ADC12CTL0 = ADC12ON+SHT0_2; // Turn on and set up ADC12, Vcc & Vss as reference 18 | ADC12CTL1 = SHP; // Use sampling timer 19 | ADC12MCTL0 = SREF0; // Vcc & Vss as reference 20 | } 21 | 22 | unsigned int ADC_Read(uint8_t channel) 23 | { 24 | int voltage; 25 | 26 | ADC_Init(); 27 | ADC12MCTL0 |= channel & 0x0F; 28 | __delay_cycles(3600); 29 | ADC12CTL0 |= ENC; // Enable conversions 30 | ADC12CTL0 |= ADC12SC; // Start conversion 31 | while ((ADC12IFG & BIT0)==0); 32 | voltage = ADC12MEM0; 33 | ADC12MCTL0 &= ~channel; // clear the channel 34 | 35 | return voltage & 0xfff ; 36 | } 37 | 38 | void ADG708_Set_Init() 39 | { 40 | IO_DIRECTION(A0, OUTPUT); 41 | IO_DIRECTION(A1, OUTPUT); 42 | IO_DIRECTION(A2, OUTPUT); 43 | } 44 | 45 | void ADG708_Set_Channel(uint8_t channel) 46 | { 47 | uint8_t a0; 48 | uint8_t a1; 49 | uint8_t a2; 50 | 51 | a0 = (channel-1) & 1; 52 | a1 = ((channel-1)>>1) & 1; 53 | a2 = ((channel-1)>>2) & 1; 54 | IO_SET(A0, a0); 55 | IO_SET(A1, a1); 56 | IO_SET(A2, a2); 57 | } 58 | 59 | uint16_t ADC_Get_Voltage_A0(uint8_t channel) 60 | { 61 | ADG708_Set_Init(); 62 | ADG708_Set_Channel(channel); 63 | __delay_cycles(3600); 64 | return ADC_Read(0); 65 | } 66 | 67 | uint16_t ADC_Get_Voltage_A1(uint8_t channel) 68 | { 69 | ADG708_Set_Init(); 70 | ADG708_Set_Channel(channel); 71 | __delay_cycles(3600); 72 | return ADC_Read(1); 73 | } 74 | -------------------------------------------------------------------------------- /lib/adc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * adc.h 3 | * 4 | * Created on: 2012. 6. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef ADC_H_ 9 | #define ADC_H_ 10 | 11 | #include 12 | 13 | #define VSOLAR 4 14 | #define VBUS 3 15 | #define VBAT 2 16 | #define VSUPERCAP 1 17 | 18 | #define SOLAR_CS1 4 19 | #define SOLAR_CS2 3 20 | #define SOLAR_CS3 2 21 | #define SOLAR_CS4 1 22 | #define SOLAR_CS5 5 23 | #define SUN_IN 6 24 | 25 | #define A0_PORT 5 26 | #define A0_PIN 5 27 | 28 | #define A1_PORT 5 29 | #define A1_PIN 6 30 | 31 | #define A2_PORT 5 32 | #define A2_PIN 7 33 | 34 | void adc_init(void); 35 | uint16_t adc_read(uint16_t channel); 36 | 37 | uint16_t ADC_Get_Voltage_A0(uint8_t channel); 38 | uint16_t ADC_Get_Voltage_A1(uint8_t channel); 39 | 40 | #endif /* ADC_H_ */ 41 | -------------------------------------------------------------------------------- /lib/adf7020.c: -------------------------------------------------------------------------------- 1 | #include "adf7020.h" 2 | #include "global.h" 3 | 4 | ////////// TEST BOARD 5 | //#define TXCLK_PORT 1 6 | //#define TXCLK_PIN 2 7 | // 8 | //#define DATA_PORT 5 9 | //#define DATA_PIN 0 10 | // 11 | //#define SCLK_PORT 5 12 | //#define SCLK_PIN 1 13 | // 14 | //#define SREAD_PORT 5 15 | //#define SREAD_PIN 2 16 | // 17 | //#define SDATA_PORT 5 18 | //#define SDATA_PIN 3 19 | // 20 | //#define SLE_PORT 5 21 | //#define SLE_PIN 4 22 | // 23 | //#define CE_PORT 5 24 | //#define CE_PIN 5 25 | // 26 | //#define PAON_PORT 2 27 | //#define PAON_PIN 7 28 | 29 | ////////// REAL BOARD 30 | #define TXCLK_PORT 2 31 | #define TXCLK_PIN 0 32 | 33 | #define DATA_PORT 2 34 | #define DATA_PIN 1 35 | 36 | #define SCLK_PORT 2 37 | #define SCLK_PIN 2 38 | 39 | #define SREAD_PORT 2 40 | #define SREAD_PIN 3 41 | 42 | #define SDATA_PORT 2 43 | #define SDATA_PIN 4 44 | 45 | #define SLE_PORT 2 46 | #define SLE_PIN 5 47 | 48 | #define CE_PORT 2 49 | #define CE_PIN 6 50 | 51 | #define PAON_PORT 2 52 | #define PAON_PIN 7 53 | 54 | 55 | // crystal 11.05920MHz 56 | //// 7020-1: 288.5/2 = 144.25 MHz 57 | //static const uint32_t adf7020_1_regs[] = { 58 | // 0x10d0b1f0, //r0 59 | // 0x0002b011, //r1 60 | // 0x800f00d2, //r2 61 | //}; 62 | 63 | // crystal 19.2MHz 64 | // PFD 6.4MHz 65 | // 7020-1: 288.5/2 = 144.25 MHz 66 | // vco bias 0.625mA 67 | static const uint32_t adf7020_1_regs[] = { 68 | 0x1168a000, //r0 69 | 0x0002b031, //r1 70 | 0x800f00d2, //r2 71 | }; 72 | 73 | 74 | //#define PA_ON (63 << 9) //-0.25 dbm = -16 + 0.45 * 35 75 | #define PA_ON (10 << 9) //-0.25 dbm = -16 + 0.45 * 35 76 | 77 | #define TX 1 78 | static unsigned char mode; 79 | 80 | void spi_write(unsigned char _register) 81 | { 82 | volatile int i; 83 | 84 | for(i = 7; i >= 0; i--) 85 | { 86 | IO_SET(SCLK, LOW); 87 | if(_register & (1<> 24-(i*8)) & 0xff; 108 | spi_write(_register); 109 | } 110 | // SLE 111 | IO_SET(SLE, HIGH); 112 | __delay_cycles(10); 113 | IO_SET(SDATA, LOW); // SDATA low 114 | IO_SET(SLE, LOW); 115 | 116 | __delay_cycles(30); 117 | 118 | } 119 | 120 | 121 | void ADF7020_1_Init() 122 | { 123 | IO_DIRECTION(DATA,OUTPUT); 124 | IO_DIRECTION(SCLK,OUTPUT); 125 | IO_DIRECTION(SREAD,OUTPUT); 126 | IO_DIRECTION(SDATA,OUTPUT); 127 | IO_DIRECTION(SLE,OUTPUT); 128 | IO_DIRECTION(CE,OUTPUT); 129 | 130 | // SCLK and SDATA pin must be LOW from start. 131 | IO_SET(DATA, LOW); 132 | IO_SET(SCLK, LOW); 133 | IO_SET(SDATA, LOW); 134 | IO_SET(SLE, LOW); 135 | 136 | } 137 | 138 | 139 | void adf7020_1_tx() 140 | { 141 | IO_SET(CE, HIGH); 142 | IO_DIRECTION(DATA,OUTPUT); 143 | __delay_cycles(1000); 144 | 145 | adf702x_write(adf7020_1_regs[1]); // once again for stable operation. 146 | __delay_cycles(4000); 147 | adf702x_write(adf7020_1_regs[0]); 148 | __delay_cycles(400); 149 | adf702x_write(adf7020_1_regs[2]); 150 | 151 | mode = TX; 152 | } 153 | 154 | void adf7020_1_poweramp(uint8_t is_pa_on) 155 | { 156 | IO_SET(DATA, LOW); 157 | 158 | if (is_pa_on==1) { 159 | adf702x_write(adf7020_1_regs[2]|PA_ON); 160 | // IO_SET(PAON, HIGH); 161 | } 162 | else { 163 | adf702x_write(adf7020_1_regs[2]); 164 | // IO_SET(PAON, LOW); 165 | } 166 | } 167 | 168 | 169 | void ADF7020_1_SendStart() 170 | { 171 | adf7020_1_tx(); 172 | __delay_cycles(1000); 173 | adf7020_1_poweramp(1); // power on 174 | __delay_cycles(1000); 175 | } 176 | 177 | void adf7020_1_ook(uint8_t is_high) 178 | { 179 | if (is_high == 1) { 180 | IO_SET(DATA, HIGH); 181 | } 182 | else { 183 | IO_SET(DATA, LOW); 184 | } 185 | mode = TX; 186 | } 187 | -------------------------------------------------------------------------------- /lib/adf7020.h: -------------------------------------------------------------------------------- 1 | /* 2 | * adf702x.h 3 | * 4 | * Created on: 2012. 5. 5. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef ADF7020_H_ 9 | #define ADF7020_H_ 10 | 11 | #include 12 | #include "global.h" 13 | 14 | void ADF7020_1_Init(void); 15 | void ADF7020_1_SendStart(void); 16 | void adf7020_1_ook(uint8_t is_pa_on); 17 | 18 | #endif /* ADF7020_H_ */ 19 | -------------------------------------------------------------------------------- /lib/adf7021n.c: -------------------------------------------------------------------------------- 1 | #include "adf7021n.h" 2 | #include "global.h" 3 | 4 | ////////////// TX 5 | 6 | #define TX_TXCLK_PORT 2 7 | #define TX_TXCLK_PIN 3 8 | 9 | #define TX_DATA_PORT 2 10 | #define TX_DATA_PIN 4 11 | 12 | #define TX_SCLK_PORT 2 13 | #define TX_SCLK_PIN 5 14 | 15 | #define TX_SREAD_PORT 2 16 | #define TX_SREAD_PIN 6 17 | 18 | #define TX_SDATA_PORT 2 19 | #define TX_SDATA_PIN 7 20 | 21 | #define TX_SLE_PORT 4 22 | #define TX_SLE_PIN 0 23 | 24 | #define TX_CE_PORT 4 25 | #define TX_CE_PIN 1 26 | 27 | #define TX_ON_PORT 4 28 | #define TX_ON_PIN 2 29 | 30 | ///////////// TX PA 31 | 32 | #define PA_ON_PORT 4 33 | #define PA_ON_PIN 4 34 | 35 | ///////////// RX 36 | 37 | #define RX_TXCLK_PORT 1 38 | #define RX_TXCLK_PIN 2 39 | 40 | #define RX_DATA_PORT 1 41 | #define RX_DATA_PIN 3 42 | 43 | #define RX_SWD_PORT 1 44 | #define RX_SWD_PIN 4 45 | 46 | #define RX_SCLK_PORT 1 47 | #define RX_SCLK_PIN 5 48 | 49 | #define RX_SREAD_PORT 1 50 | #define RX_SREAD_PIN 6 51 | 52 | #define RX_SDATA_PORT 1 53 | #define RX_SDATA_PIN 7 54 | 55 | #define RX_SLE_PORT 2 56 | #define RX_SLE_PIN 0 57 | 58 | #define RX_CE_PORT 2 59 | #define RX_CE_PIN 1 60 | 61 | #define RX_ON_PORT 4 62 | #define RX_ON_PIN 3 63 | 64 | // crystal 19.68MHz 65 | // PFD 19.68MHz 66 | // 7021-n: 433MHz 1200kbps 67 | // vco bias: 2.75mA 68 | // Xtal bias: 30uA 69 | // PA bias: 9uA 70 | // Desired Deviation: 2.102kHz 71 | // Data Rate: 1.2 kbps 72 | // IF BandWidth: 18.5kHz 73 | // Power: 12.04dBm 74 | static const uint32_t adf7021_regs[] = { 75 | 0x095FF380, //r0 76 | 0x00575011, //r1 77 | // 0x0077F082, //r2 // 12.04dBm: PA setting 63 78 | 0x0071B082, //r2 // 1dBm: PA setting 13 79 | 0x37160123, //r3 80 | 0x80293814, //r4 81 | 0x00003155, //r5 82 | }; 83 | 84 | unsigned char ShiftReg; 85 | 86 | #define bitSet(value, bit) ((value) |= (0x01 << (bit))) 87 | #define bitClear(value, bit) ((value) &= ~(0x01 << (bit))) 88 | #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) 89 | #define setShiftRegLSB(bitValue) (bitWrite(ShiftReg, 0, bitValue )) 90 | 91 | char preamble_count; 92 | unsigned char preamble_found; 93 | 94 | volatile uint8_t adf702x_buf[RF_MAX] = {0xAA, 0xAA, 0xAA, 0xAA, SYNC_WORD1, SYNC_WORD2, 0xAA, 0xAA, 0xAA, '1', '2', '3', '4', '5', '6', 0xAA, 0xAA, 0XAA}; 95 | volatile uint8_t adf702x_rx_buf[RF_MAX]; 96 | 97 | static const uint32_t adf7021_tx_reg = 0x01600850; 98 | static unsigned char mode; 99 | 100 | int bits_step =7; 101 | int bytes_step = 0; 102 | 103 | 104 | void spi_write(unsigned char _register, unsigned char mode) 105 | { 106 | volatile int i; 107 | 108 | if (mode == TX) { 109 | for(i = 7; i >= 0; i--) 110 | { 111 | IO_SET(TX_SCLK, LOW); 112 | if(_register & (1<= 0; i--) 125 | { 126 | IO_SET(RX_SCLK, LOW); 127 | if(_register & (1<> 24-(i*8)) & 0xff; 149 | spi_write(_register, mode); 150 | } 151 | // SLE 152 | if (mode == TX) { 153 | IO_SET(TX_SLE, HIGH); 154 | __delay_cycles(10); 155 | IO_SET(TX_SDATA, LOW); // SDATA low 156 | IO_SET(TX_SLE, LOW); 157 | } else if (mode == RX) { 158 | IO_SET(RX_SLE, HIGH); 159 | __delay_cycles(10); 160 | IO_SET(RX_SDATA, LOW); // SDATA low 161 | IO_SET(RX_SLE, LOW); 162 | } 163 | __delay_cycles(30); 164 | } 165 | 166 | void adf7021n_rx() 167 | { 168 | 169 | IO_SET(TX_CE, LOW); 170 | IO_SET(RX_CE, HIGH); 171 | 172 | // fill adf702x_rx_buf 173 | // r4 for 1200 bps 174 | adf702x_write(adf7021_regs[1], RX); 175 | adf702x_write(adf7021_regs[3], RX); 176 | adf702x_write(adf7021_regs[5], RX); 177 | adf702x_write(adf7021_regs[0], RX); 178 | adf702x_write(adf7021_regs[4], RX); 179 | 180 | //mode = RX; 181 | mode = IDLE; 182 | } 183 | 184 | void adf7021n_tx() 185 | { 186 | IO_SET(RX_CE, LOW); 187 | IO_SET(TX_CE, HIGH); 188 | 189 | // fill adf702x_tx_buf 190 | adf702x_write(adf7021_regs[1], TX); 191 | adf702x_write(adf7021_regs[3], TX); 192 | adf702x_write(adf7021_tx_reg, TX); 193 | adf702x_write(adf7021_regs[2], TX); 194 | adf702x_write(adf7021_regs[4], TX); 195 | 196 | mode = TX; 197 | } 198 | 199 | unsigned char adf7021n_get_mode() 200 | { 201 | return mode; 202 | } 203 | 204 | void adf7021n_enable_data_interrupt() 205 | { 206 | 207 | // RX_TXCLK is 1.2 208 | P1OUT |= BIT2; // pull up 209 | P1IE |= BIT2; // interrupt enable 210 | P1IES |= BIT2; // interrupt hi/lo falling edge 211 | P1IFG &= ~BIT2; // P1.2 IFG cleared just in case 212 | 213 | // TX_TXCLK is 2.3 214 | P2OUT |= BIT3; // pull up 215 | P2IE |= BIT3; // interrupt enable 216 | P2IES |= BIT3; // interrupt hi/lo falling edge 217 | P2IFG &= ~BIT3; // P2.3 IFG cleared just in case 218 | 219 | // data communication check! 220 | P6DIR |= BIT0; 221 | // IO_DIRECTION TODO: change IO_DIRECTION 222 | } 223 | 224 | void adf7021n_recvStart() 225 | { 226 | adf7021n_enable_data_interrupt(); 227 | adf7021n_rx(); 228 | } 229 | 230 | void TX_PA_PowerOn() 231 | { 232 | IO_DIRECTION(PA_ON, OUTPUT); 233 | IO_SET(PA_ON, HIGH); 234 | } 235 | 236 | void adf7021n_setTxPaLevel() 237 | { 238 | // TODO: make change level. 239 | // adf702x_write(adf7021_regs[2] , TX); 240 | } 241 | 242 | void adf7021n_sendStart() 243 | { 244 | adf7021n_enable_data_interrupt(); 245 | TX_PA_PowerOn(); 246 | adf7021n_tx(); 247 | } 248 | 249 | void adf7021n_init() 250 | { 251 | IO_DIRECTION(TX_DATA, OUTPUT); 252 | IO_DIRECTION(TX_SCLK, OUTPUT); 253 | IO_DIRECTION(TX_SDATA, OUTPUT); 254 | IO_DIRECTION(TX_SLE, OUTPUT); 255 | IO_DIRECTION(TX_CE, OUTPUT); 256 | 257 | IO_DIRECTION(RX_DATA, INPUT); 258 | IO_DIRECTION(RX_SCLK, OUTPUT); 259 | IO_DIRECTION(RX_SDATA, OUTPUT); 260 | IO_DIRECTION(RX_SLE, OUTPUT); 261 | IO_DIRECTION(RX_CE, OUTPUT); 262 | 263 | // SCLK and SDATA pin must be LOW from start. 264 | IO_SET(TX_SCLK, LOW); 265 | IO_SET(TX_SDATA, LOW); 266 | // IO_SET(TX_SLE, LOW); 267 | 268 | IO_SET(RX_SCLK, LOW); 269 | IO_SET(RX_SDATA, LOW); 270 | // IO_SET(RX_SLE, LOW); 271 | 272 | // CE is HIGH 273 | IO_SET(RX_CE, HIGH); 274 | IO_SET(TX_CE, HIGH); 275 | } 276 | 277 | 278 | // Port 2 interrupt service routine 279 | #pragma vector=PORT2_VECTOR 280 | __interrupt void adf7021n_Data_Tx_handler(void) 281 | { 282 | switch (mode) { 283 | case TX: 284 | if(adf702x_buf[bytes_step] & (1<= 15){ 294 | bytes_step = 0; bits_step=7; 295 | P6OUT ^= BIT0; 296 | }; 297 | 298 | break; 299 | } 300 | P2IFG &= ~BIT3; // P2.3 IFG cleared 301 | } 302 | 303 | // Port 1 interrupt service routine 304 | #pragma vector=PORT1_VECTOR 305 | __interrupt void adf7021n_Data_Rx_handler(void) 306 | { 307 | switch (mode) { 308 | case RX: 309 | ShiftReg = ShiftReg << 1; 310 | // setShiftRegLSB(P5IN & BIT0); 311 | setShiftRegLSB(P1IN & BIT3); 312 | 313 | bits_step++; 314 | 315 | if (bits_step == 8) { 316 | bits_step = 0; 317 | switch(bytes_step){ 318 | case 0: 319 | if (ShiftReg != SYNC_WORD2) { 320 | mode = IDLE; 321 | } 322 | break; 323 | case 1: 324 | // header 0 325 | break; 326 | case 2: 327 | // header 1 328 | break; 329 | case 3: 330 | // byte size 331 | break; 332 | default: 333 | adf702x_rx_buf[bytes_step-4] = ShiftReg; 334 | } 335 | 336 | if(bytes_step > 4+6){ // 6 is data length 337 | P6OUT ^= BIT0; 338 | bytes_step = 0; 339 | mode = IDLE; 340 | // CE LOW? 341 | } 342 | bytes_step++; 343 | 344 | } 345 | break; 346 | 347 | case IDLE: 348 | ShiftReg=ShiftReg<<1; 349 | // setShiftRegLSB(P5IN & BIT0); RX_DATA 350 | setShiftRegLSB(P1IN & BIT3); 351 | 352 | if (preamble_found == 1) { 353 | if (ShiftReg == SYNC_WORD1) { 354 | bits_step=0; 355 | bytes_step=0; 356 | preamble_count=0; 357 | preamble_found=0; 358 | mode = RX; 359 | } 360 | break; 361 | } 362 | 363 | if ((ShiftReg == VALID_PREAMBLE_BYTE_1) || (ShiftReg == VALID_PREAMBLE_BYTE_2)) { 364 | preamble_count++; 365 | } else { 366 | preamble_count = 0; 367 | preamble_found = 0; //false 368 | } 369 | 370 | if (preamble_count >= 16) { 371 | preamble_found = 1; //false 372 | } 373 | break; 374 | } 375 | P1IFG &= ~BIT2; // P1.2 IFG cleared 376 | } 377 | -------------------------------------------------------------------------------- /lib/adf7021n.h: -------------------------------------------------------------------------------- 1 | /* 2 | * adf7021n.h 3 | * 4 | * Created on: 2012. 6. 18. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef ADF7021N_H_ 9 | #define ADF7021N_H_ 10 | 11 | #include 12 | #include "global.h" 13 | 14 | void adf7021n_init(void); 15 | void adf7021n_sendStart(void); 16 | void adf7021n_recvStart(void); 17 | 18 | void adf7021n_tx(void); 19 | void adf7021n_rx(void); 20 | 21 | unsigned char adf7021n_get_mode(void); 22 | 23 | #define IDLE 0 24 | #define TX 1 25 | #define RX 2 26 | 27 | #define RF_MAX 64 28 | #define PREAMBLE_BYTE 0xAA 29 | 30 | #define VALID_PREAMBLE_BYTE_1 0x55 31 | #define VALID_PREAMBLE_BYTE_2 0xAA 32 | 33 | #define SYNC_WORD1 0xD3 // First byte of sync word 34 | #define SYNC_WORD2 0x91 // Second byte of sync word 35 | 36 | #define HEADER_SIZE 4 // 4 bytes header 37 | 38 | #define ON TRUE 39 | #define OFF FALSE 40 | 41 | #define adf702x_data (adf702x_buf + 3) 42 | 43 | 44 | #endif /* ADF7021N_H_ */ 45 | -------------------------------------------------------------------------------- /lib/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * config.h 3 | * 4 | * Created on: 2012. 6. 9. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef CONFIG_H_ 9 | #define CONFIG_H_ 10 | 11 | #define EEPROM_ADDR 0x50 12 | #define PANELTEMP_ADDR 0x4A 13 | #define OBCTEMP_ADDR 0x48 14 | #define PCA9548A_ADDR 0x70 15 | #define PCA9548A_CHANNEL3 8 16 | #define PCA9548A_CH_PANELTEMP 3 17 | #define PCA9548A_CH_PAYLOAD 2 18 | 19 | #define PCA9548A_RESET_PORT 3 20 | #define PCA9548A_RESET_PIN 1 21 | 22 | #endif /* CONFIG_H_ */ 23 | -------------------------------------------------------------------------------- /lib/global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * global.h 3 | * 4 | * Created on: 2012. 6. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef GLOBAL_H_ 9 | #define GLOBAL_H_ 10 | 11 | 12 | // Macros for turning on and off the LEDs (for testing only) 13 | enum {FALSE = 0, TRUE = 1}; 14 | #define _BV(bit) (1<<(bit)) 15 | 16 | typedef unsigned char uint8_t; 17 | typedef signed char int8_t; 18 | typedef unsigned short int uint16_t; 19 | typedef signed short int int16_t; 20 | typedef unsigned long int uint32_t; 21 | typedef signed long int int32_t; 22 | 23 | //macros for IO config (with preprocessor abuse) 24 | #define st(x) do{x} while(__LINE__ == -1) 25 | 26 | enum IoState {LOW = 0, HIGH = 1, TOGGLE = 2}; 27 | #define IO_SET(name,val) _IO_SET(name##_PORT,name##_PIN,val) 28 | #define _IO_SET(port,pin,val) st(__IO_SET(port,pin,val);) 29 | #define __IO_SET(port,pin,val) if (val == TOGGLE)\ 30 | {\ 31 | st((P##port##OUT ^= _BV(pin)););\ 32 | }\ 33 | else if (val == HIGH)\ 34 | {\ 35 | st((P##port##OUT |= _BV(pin)););\ 36 | }\ 37 | else\ 38 | {\ 39 | st((P##port##OUT &= ~_BV(pin)););\ 40 | } 41 | 42 | enum IoDirection {INPUT = 0, OUTPUT = 1}; 43 | #define IO_DIRECTION(name,dir) _IO_DIRECTION(name##_PORT,name##_PIN,dir) 44 | 45 | #define _IO_DIRECTION(port,pin,dir) st(__IO_DIRECTION(port,pin,dir);) 46 | #define __IO_DIRECTION(port,pin,dir) if (dir)\ 47 | {\ 48 | st((P##port##DIR |= _BV(pin)););\ 49 | }\ 50 | else\ 51 | {\ 52 | st((P##port##DIR &= ~_BV(pin)););\ 53 | } 54 | 55 | #endif /* GLOBAL_H_ */ 56 | -------------------------------------------------------------------------------- /lib/i2c.c: -------------------------------------------------------------------------------- 1 | #include "i2c.h" 2 | 3 | unsigned char I2CBuffer[3]; 4 | int PtrTransmit; 5 | int PtrReceive; 6 | 7 | int NACK_Count; 8 | 9 | /*---------------------------------------------------------------------------*/ 10 | void InitI2C(uint8_t slave_address) 11 | // Description: 12 | // Initialization of the I2C Module 13 | { 14 | NACK_Count =0; 15 | 16 | P3SEL = 0x0A; // select module function for the used I2C pins 17 | P3DIR &= ~0x0A; 18 | 19 | // Recommended initialisation steps of I2C module as shown in User Guide: 20 | U0CTL |= I2C+SYNC; // (1) Select I2C mode with SWRST=1 21 | U0CTL &= ~I2CEN; // (2) disable the I2C module 22 | // (3) Configure the I2C module with I2CEN=0 : 23 | // U0CTL default settings: 24 | // 7-bit addressing, no DMA, no feedback 25 | I2CTCTL = I2CTRX+I2CSSEL_2; // byte mode, repeat mode, clock source = SMCLK, 26 | // transmit mode 27 | I2CSA = slave_address; // define Slave Address 28 | // In this case the Slave Address defines the 29 | // control byte that is sent to the EEPROM. 30 | // I2CPSC = 0x00; // I2C clock = clock source/1 31 | // I2CTCTL = I2CSSEL_1; // SMCLK 32 | 33 | I2CSCLH = 0x03; // SCL high period = 5*I2C clock 34 | I2CSCLL = 0x03; // SCL low period = 5*I2C clock 35 | U0CTL |= I2CEN; // (4) set I2CEN via software 36 | 37 | } 38 | 39 | 40 | 41 | void I2CWriteInit(void) 42 | // Description: 43 | // Initialization of the I2C Module for Write operation. 44 | { 45 | U0CTL |= MST; // define Master Mode 46 | I2CTCTL |= I2CTRX; // I2CTRX=1 => Transmit Mode (R/W bit = 0) 47 | I2CIFG &= ~TXRDYIFG; 48 | I2CIE = TXRDYIE; // enable Transmit ready interrupt 49 | } 50 | 51 | /*---------------------------------------------------------------------------*/ 52 | void I2CReadInit(void) 53 | // Description: 54 | // Initialization of the I2C Module for Read operation. 55 | { 56 | I2CTCTL &= ~I2CTRX; // I2CTRX=0 => Receive Mode (R/W bit = 1) 57 | I2CIE = RXRDYIE; // enable Receive ready interrupt 58 | } 59 | 60 | //// I2C Interrupt Vector (I2CIV) handler 61 | #pragma vector=USART0TX_VECTOR 62 | __interrupt void I2C_ISR (void) 63 | { 64 | switch( I2CIV ) 65 | { 66 | case 2: break; // Arbitration lost 67 | case 4: 68 | { 69 | break; // No Acknowledge 70 | } 71 | case 6: break; // Own Address 72 | case 8: break; // Register Access Ready 73 | case 10: 74 | { 75 | 76 | I2CBuffer[PtrReceive]=I2CDRB; // store received data in buffer 77 | PtrReceive = PtrReceive-1; 78 | if (PtrReceive < 0) 79 | { 80 | I2CIE &= ~RXRDYIE; // disable interrupts 81 | } 82 | break; 83 | } 84 | case 12: 85 | { 86 | I2CDRB = I2CBuffer[PtrTransmit]; 87 | PtrTransmit = PtrTransmit-1; 88 | 89 | if (PtrTransmit <0) 90 | { 91 | I2CIE &= ~TXRDYIE; // disable interrupts 92 | } 93 | break; 94 | } 95 | case 14: break; // General Call 96 | case 16: break; // Start Condition 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * i2c.h 3 | * 4 | * Created on: 2012. 5. 24. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef I2C_H_ 9 | #define I2C_H_ 10 | 11 | #include 12 | #include "global.h" 13 | 14 | void InitI2C(uint8_t slave_address); 15 | void I2CWriteInit(); 16 | void I2CReadInit(); 17 | 18 | extern unsigned char I2CBuffer[3]; 19 | extern int PtrTransmit; 20 | extern int PtrReceive; 21 | 22 | #endif /* I2C_H_ */ 23 | -------------------------------------------------------------------------------- /lib/morse.c: -------------------------------------------------------------------------------- 1 | #include "morse.h" 2 | #include "adf7020.h" 3 | 4 | //uint8_t done = 0b10000000; 5 | uint8_t done = 0x80; 6 | uint8_t output_pin; 7 | 8 | void delay(void) 9 | { 10 | volatile unsigned int i; 11 | // i = 10000; // Delay 12 | i = 5000; // Delay 13 | do (i--); 14 | while (i != 0); 15 | } 16 | 17 | void mark(uint8_t t) 18 | { 19 | volatile unsigned int i; 20 | adf7020_1_ook(1); 21 | // P1OUT &= ~BIT1; 22 | LED_ON(); 23 | for(i = 0; i < t; i++) 24 | { // Turn On 25 | delay(); 26 | } 27 | adf7020_1_ook(0); 28 | LED_OFF(); // Turn Off 29 | delay(); 30 | } 31 | 32 | void space(uint8_t t) 33 | { 34 | volatile unsigned int i; 35 | adf7020_1_ook(0); 36 | LED_OFF(); 37 | 38 | for(i = 0; i < t; i++) 39 | { 40 | delay(); 41 | } 42 | } 43 | 44 | void morse(uint8_t m) 45 | { 46 | while (m != done) { 47 | mark(m & done ? 3 : 1); 48 | space(1); m = m << 1; 49 | } 50 | space(3); 51 | } 52 | 53 | 54 | void ascii(char c) { 55 | P1DIR |= BIT1; 56 | uint8_t number_code[] = { 57 | // 0b11111100, 0b01111100, 0b00111100, 0b00011100, 0b00001100, 0b00000100, 58 | // 0b10000100, 0b11000100, 0b11100100, 0b11110100 // 0-9 59 | 0xfc, 0x7c, 0x3c, 0x1c, 0xc, 0x4, 0x84, 0xc4, 0xe4, 0xf4 60 | }; 61 | 62 | uint8_t alphabet_code[] = { 63 | // 0b01100000, 0b10001000, 0b10101000, 0b10010000, 0b01000000, 0b00101000, 64 | // 0b11010000, 0b00001000, 0b00100000, 0b01111000, 0b10110000, 0b01001000, 65 | // 0b11100000, 0b10100000, 0b11110000, 0b01101000, 0b11011000, 0b01010000, 66 | // 0b00010000, 0b11000000, 0b00110000, 0b00011000, 0b01110000, 0b10011000, 67 | // 0b10111000, 0b11001000 // A-Z 68 | 0x60, 0x88, 0xa8, 0x90, 0x40, 0x28, 0xd0, 0x8, 0x20, 0x78, 0xb0, 0x48, 0xe0, 0xa0, 0xf0, 0x68, 0xd8, 0x50, 0x10, 0xc0, 0x30, 0x18, 0x70, 0x98, 0xb8, 0xc8 69 | }; 70 | 71 | if (c >= '0' && c <= '9') { 72 | morse(number_code[c- '0']); 73 | } else if (c >= 'a' && c <= 'z') { 74 | morse(alphabet_code[c - 'a']); 75 | } else if (c == ' ') { 76 | space(7); 77 | } else { 78 | morse(done); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/morse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * morse.h 3 | * 4 | * Created on: 2012. 4. 26. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef MORSE_H_ 9 | #define MORSE_H_ 10 | 11 | #include 12 | #include "global.h" 13 | 14 | #define LED_PORT 1 15 | #define LED_PIN 1 16 | 17 | //#define LED_ON() IO_SET(LED,HIGH) 18 | //#define LED_OFF() IO_SET(LED,LOW) 19 | 20 | #define LED_ON() 21 | #define LED_OFF() 22 | 23 | void ascii(char c); 24 | 25 | #endif /* MORSE_H_ */ 26 | -------------------------------------------------------------------------------- /lib/payload.h: -------------------------------------------------------------------------------- 1 | /* 2 | * morse.h 3 | * 4 | * Created on: 2012. 4. 26. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef PAYLOAD_H_ 9 | #define PAYLOAD_H_ 10 | 11 | #include 12 | #include "global.h" 13 | 14 | typedef enum { 15 | PING = 0, 16 | LIGHT_ON = 1, 17 | LIGHT_OFF = 2, 18 | } PAYLOAD_CMD_ID; 19 | 20 | typedef struct Command 21 | { 22 | PAYLOAD_CMD_ID id; 23 | uint8_t length; 24 | uint8_t data; 25 | } Command; 26 | 27 | typedef struct Command CMD; 28 | 29 | #endif /* PAYLOAD_H_ */ 30 | -------------------------------------------------------------------------------- /lib/pca9548a.c: -------------------------------------------------------------------------------- 1 | #include "pca9548a.h" 2 | #include "i2c.h" 3 | #include "config.h" 4 | 5 | void PCA9548A_Reset(void) 6 | { 7 | IO_SET(PCA9548A_RESET, LOW); 8 | __delay_cycles(100000); 9 | IO_SET(PCA9548A_RESET, HIGH); 10 | __delay_cycles(100000); 11 | } 12 | 13 | void PCA9548A_Init(uint8_t slave_address) 14 | { 15 | PCA9548A_Reset(); 16 | _EINT(); 17 | InitI2C(slave_address); 18 | } 19 | 20 | void PCA9548A_SetChannel(uint8_t channel) 21 | { 22 | uint8_t control_register; 23 | 24 | while (I2CDCTL&I2CBB); 25 | control_register = 1 << channel; // select channel 26 | I2CBuffer[0] = control_register; 27 | PtrTransmit = 0; 28 | 29 | I2CWriteInit(); 30 | I2CNDAT = 1; 31 | I2CTCTL |= I2CSTT+I2CSTP; // start and stop condition generation 32 | } 33 | -------------------------------------------------------------------------------- /lib/pca9548a.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PCA9548A.h 3 | * 4 | * Created on: 2012. 5. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef PCA9548A_H_ 9 | #define PCA9548A_H_ 10 | 11 | #include 12 | #include "i2c.h" 13 | #include "global.h" 14 | 15 | void PCA9548A_SetChannel(uint8_t channel); 16 | void PCA9548A_Init(uint8_t slave_address); 17 | //uint8_t PCA9548A_GetChannel(void); 18 | 19 | #endif /* PCA9548A_H_ */ 20 | -------------------------------------------------------------------------------- /lib/tmp10x.c: -------------------------------------------------------------------------------- 1 | #include "24lc256.h" 2 | #include "i2c.h" 3 | 4 | void TMP10x_Init(uint8_t slave_address) 5 | { 6 | _EINT(); 7 | InitI2C(slave_address); 8 | } 9 | 10 | 11 | uint16_t TMP10x_Read() 12 | { 13 | uint8_t point_register; 14 | uint16_t tempature; 15 | 16 | // while (I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations 17 | while (I2CDCTL&I2CBB); 18 | 19 | point_register = 0; // Temperature Register 20 | I2CBuffer[0] = point_register; 21 | PtrTransmit = 0; 22 | 23 | I2CWriteInit(); 24 | I2CNDAT = 1; 25 | I2CIFG &= ~ARDYIFG; 26 | I2CTCTL |= I2CSTT; 27 | while ((~I2CIFG)&ARDYIFG); // wait untill transmission is finished 28 | 29 | I2CReadInit(); 30 | I2CNDAT = 2; // 2 byte should be received 31 | PtrReceive = 1; 32 | 33 | I2CIFG &= ~ARDYIFG; // clear Access ready interrupt flag 34 | I2CTCTL |= I2CSTT+I2CSTP; // start receiving and finally generate 35 | // re-start and stop condition 36 | while ((~I2CIFG)&ARDYIFG); // wait untill transmission is finished 37 | tempature = I2CBuffer[1]; 38 | tempature = (tempature << 4)|(I2CBuffer[0]>>4); 39 | return tempature; 40 | } 41 | -------------------------------------------------------------------------------- /lib/tmp10x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tmp10x.h 3 | * 4 | * Created on: 2012. 5. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef TMP10x_H_ 9 | #define TMP10x_H_ 10 | 11 | #include 12 | #include "i2c.h" 13 | #include "global.h" 14 | 15 | uint16_t TMP10X_Read(void); 16 | void TMP10x_Init(uint8_t slave_address); 17 | 18 | 19 | #endif /* TMP10x_H_ */ 20 | -------------------------------------------------------------------------------- /lib/uart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "morse.h" 3 | #include "global.h" 4 | 5 | char uart_buffer[255]; 6 | 7 | uint8_t step = 0; 8 | uint8_t sending = 0; 9 | 10 | void initUart() { 11 | P3SEL |= 0x30; // P3.4,5 = USART0 TXD/RXD 12 | ME1|= UTXE0 + URXE0; // Enable USART0 TXD/RXD 13 | UCTL0 |= CHAR; // 8-bit character 14 | UTCTL0 |= SSEL0; // UCLK = ACLK 15 | UBR00 = 0x03; // 32k/9600 - 3.41 16 | UBR10 = 0x00; // 17 | UMCTL0 = 0x4A; // Modulation 18 | UCTL0 &= ~SWRST; // Initialize USART state machine 19 | IE1 |= URXIE0; // Enable USART0 RX interrupt 20 | } 21 | 22 | void init_txrx_interrupt() 23 | { 24 | P1OUT = BIT2; //pull up 25 | P1IE |= BIT2; // interrupt enable 26 | P1IES |= BIT2; // interrupt hi/lo falling edge 27 | //P1IES &= ~BIT2; // interrupt lo/hi edge 28 | P1IFG &= ~BIT2; // P1.2 IFG cleared just in case 29 | 30 | P5DIR |= BIT0; // TX 31 | 32 | } 33 | #pragma vector=USART0RX_VECTOR 34 | __interrupt void usart0_rx (void) 35 | { 36 | 37 | while (!(IFG1 & UTXIFG0)); // USART1 TX buffer ready? 38 | TXBUF0 = RXBUF0; // RXBUF1 to TXBUF1 39 | uart_buffer[step] = RXBUF0; 40 | 41 | _EINT(); 42 | 43 | step++; 44 | if (RXBUF0 == 13) // CR 45 | { 46 | //P6OUT ^= 0x01; 47 | sending = 1; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /obc/blink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define LED_PORT 1 5 | #define LED_PIN 1 6 | 7 | void _delay() { 8 | volatile unsigned int i; // volatile to prevent optimization 9 | i = 10000; // SW Delay 10 | do i--; 11 | while(i != 0); 12 | } 13 | 14 | void _blink() { 15 | IO_SET(LED,TOGGLE); 16 | _delay(); 17 | } 18 | 19 | void infinite_blink() { 20 | IO_DIRECTION(LED, OUTPUT); 21 | for(;;) { 22 | _blink(); 23 | } 24 | } 25 | 26 | void three_blink() { 27 | volatile uint8_t i; 28 | IO_DIRECTION(LED, OUTPUT); 29 | for(i=0;i<7;i++) { 30 | _blink(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /obc/i2c_payload.c: -------------------------------------------------------------------------------- 1 | #include "i2c.h" 2 | #include "config.h" 3 | #include "payload.h" 4 | 5 | void I2C_PAYLOAD_Init(uint8_t slave_address) 6 | { 7 | _EINT(); 8 | InitI2C(slave_address); 9 | } 10 | 11 | void I2C_PAYLOAD_Write(uint8_t value) 12 | { 13 | // while (I2CDCTL&I2CBUSY); // I2C module busy 14 | while (I2CDCTL&I2CBB); // I2C bus busy. from TI forum http://goo.gl/Gsxsw http://www.ti.com/lit/er/slaz018d/slaz018d.pdf 15 | 16 | I2CBuffer[0] = value; 17 | PtrTransmit = 0; 18 | 19 | I2CWriteInit(); 20 | I2CNDAT = 1; 21 | I2CTCTL |= I2CSTT+I2CSTP; // start and stop condition generation 22 | } 23 | 24 | void I2C_PAYLOAD_Writes(CMD _cmd) 25 | { 26 | while (I2CDCTL&I2CBB); // I2C bus busy. from TI forum http://goo.gl/Gsxsw http://www.ti.com/lit/er/slaz018d/slaz018d.pdf 27 | 28 | I2CBuffer[0] = _cmd.data; 29 | I2CBuffer[1] = _cmd.length; 30 | I2CBuffer[2] = _cmd.id; 31 | PtrTransmit = _cmd.length+1; 32 | 33 | I2CWriteInit(); 34 | I2CNDAT = _cmd.length+2; 35 | I2CTCTL |= I2CSTT+I2CSTP; // start and stop condition generation 36 | } 37 | 38 | void Payload_Init(void) 39 | { 40 | I2C_PAYLOAD_Init(0x48); 41 | } 42 | 43 | void Payload_Light_On(void) 44 | { 45 | CMD c; 46 | c.id = LIGHT_ON; 47 | c.length = 1; 48 | c.data = 1; 49 | I2C_PAYLOAD_Writes(c); 50 | } 51 | 52 | void Payload_Light_Off(void) 53 | { 54 | CMD c; 55 | c.id = LIGHT_OFF; 56 | c.length = 1; 57 | c.data = 0; 58 | I2C_PAYLOAD_Writes(c); 59 | } 60 | -------------------------------------------------------------------------------- /obc/i2c_payload.h: -------------------------------------------------------------------------------- 1 | /* 2 | * I2C_PAYLOAD.h 3 | * 4 | * Created on: 2012. 5. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef I2C_PAYLOAD_H_ 9 | #define I2C_PAYLOAD_H_ 10 | 11 | #include 12 | #include "i2c.h" 13 | #include "global.h" 14 | 15 | void I2C_PAYLOAD_Write(uint8_t value); 16 | void I2C_PAYLOAD_Init(uint8_t slave_address); 17 | //uint8_t I2C_PAYLOAD_GetChannel(void); 18 | 19 | #endif /* I2C_PAYLOAD_H_ */ 20 | -------------------------------------------------------------------------------- /obc/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | .__ ____ 4 | ____ ______ ______|__| /_ | 5 | / _ \ / ___/ / ___/| | ______ | | 6 | ( <_> )\___ \ \___ \ | | /_____/ | | 7 | \____//____ >/____ >|__| |___| 8 | \/ \/ 9 | 10 | _____ _____ ______ 11 | | _ / __ \| ___ \ 12 | | | | | / \/| |_/ / 13 | | | | | | | ___ \ 14 | \ \_/ / \__/\| |_/ / 15 | \___/ \____/\____/ 16 | 17 | * Created on: 2012. 6. 3. 18 | * 19 | * 20 | */ 21 | 22 | 23 | #include 24 | #include "morse.h" 25 | #include "config.h" 26 | #include "24lc256.h" 27 | #include "pca9548a.h" 28 | #include "adc.h" 29 | 30 | char message[255] = {'1','2','3','l','o',' ','o','s','s','i',' ', '1'}; 31 | 32 | void test_antenner_deploy(void) { 33 | Ant_Deploy_Init(); 34 | Start_Ant_Deploy_After(5); 35 | } 36 | 37 | void test_tmp101(void) { 38 | // OBC temp sensor 39 | volatile uint16_t temp; 40 | 41 | TMP10x_Init(OBCTEMP_ADDR); 42 | temp = TMP10x_Read(); // C = temp / 0x10 43 | } 44 | 45 | void test_eeprom(void) { 46 | volatile unsigned int i; 47 | volatile unsigned char x; 48 | 49 | EEPROM_Init(EEPROM_ADDR); 50 | 51 | for(i=0; i < 1;i++ ) { 52 | ascii(message[i]); 53 | EEPROM_ByteWrite(i, message[i]); 54 | EEPROM_AckPolling(); 55 | } 56 | 57 | for(i=0; i < 1;i++ ) { 58 | x=EEPROM_RandomRead(i); 59 | ascii(x); 60 | } 61 | } 62 | 63 | void test_panneltemp() 64 | { 65 | volatile uint16_t temp; 66 | volatile uint8_t x; 67 | 68 | PCA9548A_Init(PCA9548A_ADDR); 69 | PCA9548A_SetChannel(PCA9548A_CH_PANELTEMP); 70 | 71 | TMP10x_Init(PANELTEMP_ADDR); 72 | temp = TMP10x_Read(); // C = temp / 0x10 73 | temp = temp+1; 74 | if ((temp/16) > 28) 75 | LED_ON(); 76 | else 77 | LED_OFF(); 78 | } 79 | 80 | void test_payload() 81 | { 82 | PCA9548A_Init(PCA9548A_ADDR); 83 | PCA9548A_SetChannel(2); 84 | 85 | Payload_Init(); 86 | while(1) { 87 | Payload_Light_Off(); 88 | _delay(); 89 | Payload_Light_On(); 90 | _delay(); 91 | } 92 | } 93 | 94 | void test_payload_with_tmp100() 95 | { 96 | volatile uint16_t temp; 97 | volatile uint8_t x; 98 | 99 | PCA9548A_Init(PCA9548A_ADDR); 100 | PCA9548A_SetChannel(PCA9548A_CH_PANELTEMP); 101 | 102 | TMP10x_Init(PANELTEMP_ADDR); 103 | temp = TMP10x_Read(); // C = temp / 0x10 104 | temp = temp+1; 105 | 106 | PCA9548A_Init(PCA9548A_ADDR); 107 | PCA9548A_SetChannel(2); 108 | 109 | Payload_Init(); 110 | 111 | if ((temp/16) > 29) 112 | Payload_Light_On(); 113 | else 114 | Payload_Light_Off(); 115 | _delay(); 116 | 117 | } 118 | 119 | void test_adc(void) 120 | { 121 | volatile uint16_t v; 122 | 123 | v = ADC_Get_Voltage_A1(VSOLAR); 124 | v = v+1; 125 | v = ADC_Get_Voltage_A1(VBUS); 126 | v = v+1; 127 | v = ADC_Get_Voltage_A1(VBAT); 128 | v = v+1; 129 | v = ADC_Get_Voltage_A1(VSUPERCAP); 130 | v = v+1; 131 | 132 | v = ADC_Get_Voltage_A0(SOLAR_CS1); 133 | v = v+1; 134 | v = ADC_Get_Voltage_A0(SOLAR_CS2); 135 | v = v+1; 136 | v = ADC_Get_Voltage_A0(SOLAR_CS3); 137 | v = v+1; 138 | v = ADC_Get_Voltage_A0(SOLAR_CS4); 139 | v = v+1; 140 | v = ADC_Get_Voltage_A0(SOLAR_CS5); 141 | v = v+1; 142 | v = ADC_Get_Voltage_A0(SUN_IN); 143 | v = v+1; 144 | } 145 | 146 | void test_watchdog(void) 147 | { 148 | Watchdog_External_Init(); 149 | } 150 | 151 | int main(void) { 152 | 153 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 154 | test_watchdog(); 155 | 156 | IO_DIRECTION(LED, OUTPUT); 157 | 158 | three_blink(); 159 | 160 | // test_eeprom(); 161 | // test_tmp101(); 162 | // test_payload(); 163 | // while(1) 164 | // test_payload_with_tmp100(); 165 | 166 | // while(1) { 167 | // test_panneltemp(); 168 | // } 169 | // test_antenner_deploy(); 170 | while(1) 171 | test_adc(); 172 | 173 | infinite_blink(); 174 | } 175 | 176 | -------------------------------------------------------------------------------- /obc/watchdog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #define WATCHDOG_IN_PORT 1 6 | #define WATCHDOG_IN_PIN 0 7 | 8 | 9 | void Watchdog_External_Init() { 10 | WDTCTL = WDT_ADLY_1000; // WDT 1000ms, ACLK, interval timer 11 | IE1 |= WDTIE; // Enable WDT interrupt 12 | IO_DIRECTION(WATCHDOG_IN, OUTPUT); 13 | _BIS_SR(GIE); 14 | } 15 | 16 | // Watchdog Timer interrupt service routine 17 | #pragma vector=WDT_VECTOR 18 | __interrupt void watchdog_timer(void) 19 | { 20 | IO_SET(WATCHDOG_IN, TOGGLE); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /payload/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | .__ ____ 4 | ____ ______ ______|__| /_ | 5 | / _ \ / ___/ / ___/| | ______ | | 6 | ( <_> )\___ \ \___ \ | | /_____/ | | 7 | \____//____ >/____ >|__| |___| 8 | \/ \/ 9 | 10 | ______ _ _ 11 | | ___ \ | | | | 12 | | |_/ /_ _ _ _| | ___ __ _ __| | 13 | | __/ _` | | | | |/ _ \ / _` |/ _` | 14 | | | | (_| | |_| | | (_) | (_| | (_| | 15 | \_| \__,_|\__, |_|\___/ \__,_|\__,_| 16 | __/ | 17 | |___/ 18 | 19 | * MSP430F2012 20 | * 21 | * Created on: 2012. 6. 3. 22 | * 23 | * 24 | */ 25 | #include "msp430x20x2.h" 26 | #include "payload.h" 27 | 28 | #define LED_PORT 1 29 | #define LED_PIN 1 30 | 31 | #define PWM_PORT 1 32 | #define PWM_PIN 5 33 | 34 | int PtrReceive=0; 35 | 36 | uint8_t cmd; 37 | uint8_t length; 38 | uint8_t data; 39 | 40 | //int I2C_Slave_Init(uint16_t address) 41 | //{ 42 | // P3SEL |= 0x0A; // Select I2C pins 43 | // U0CTL |= I2C + SYNC; // Recommended init procedure 44 | // U0CTL &= ~I2CEN; // Recommended init procedure 45 | // I2CTCTL |= I2CSSEL1; // SMCLK 46 | // I2COA = 0x0048; // Own Address is 048h 47 | // I2CIE = RXRDYIE; // Enable RXRDYIFG interrupt 48 | // U0CTL |= I2CEN; // Enable I2C 49 | //} 50 | 51 | void LED_Init(void) { 52 | P1DIR |= BIT2; // P1.2 output 53 | P1SEL |= BIT2; // P1.2 TA1 options 54 | } 55 | 56 | void LED_On(void) { 57 | CCR0 = 500; // PWM Period 58 | CCTL1 = OUTMOD_7; // CCR1 reset/set 59 | CCR1 = 150; // CCR1 PWM duty cycle 60 | TACTL = TASSEL_2 + MC_1; // SMCLK, up mode 61 | } 62 | 63 | void LED_Off(void) { 64 | TACTL = ~TAIE; 65 | } 66 | 67 | void LED_Blink(uint32_t on_time, uint32_t off_time) 68 | { 69 | LED_On(); 70 | 71 | __delay_cycles(150000); 72 | 73 | LED_Off(); 74 | 75 | __delay_cycles(150000); 76 | } 77 | 78 | int main(void) { 79 | volatile unsigned int i; 80 | volatile unsigned int x; 81 | volatile unsigned int z; 82 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 83 | _EINT(); 84 | 85 | LED_Init(); 86 | 87 | while(1) 88 | LED_Blink(150000, 150000); 89 | } 90 | 91 | void parse_command(uint8_t i2c_data) 92 | { 93 | if (PtrReceive == 0) { 94 | cmd = i2c_data; 95 | } 96 | if (PtrReceive == 1) { 97 | length = i2c_data; 98 | } 99 | if (PtrReceive == 2) 100 | { 101 | data = i2c_data; //TODO: It just one byte. 102 | } 103 | 104 | if (PtrReceive == length+1) 105 | { 106 | if (data == 0) { 107 | LED_OFF(); 108 | } 109 | if (data == 1) { 110 | LED_ON(); 111 | } 112 | PtrReceive = -1; 113 | } 114 | 115 | PtrReceive = PtrReceive+1; 116 | } 117 | 118 | 119 | //// Common ISR for I2C Module 120 | //#pragma vector=USART0TX_VECTOR 121 | //__interrupt void I2C_ISR(void) 122 | //{ 123 | // switch( I2CIV ) 124 | // { 125 | // case 2: break; // Arbitration lost 126 | // case 4: break; // No Acknowledge 127 | // case 6: break; // Own Address 128 | // case 8: break; // Register Access Ready 129 | // case 10: // Receive Ready 130 | // parse_command(I2CDRB); 131 | // break; 132 | //// 133 | //// RXData = I2CDRB; // RX data 134 | //// if (RXData > 0) { 135 | //// LED_ON(); 136 | //// }else { 137 | //// LED_OFF(); 138 | //// } 139 | //// _BIC_SR_IRQ(CPUOFF); // Clear LPM0 140 | // break; 141 | // case 12: break; // Transmit Ready 142 | // case 14: break; // General Call 143 | // case 16: break; // Start Condition 144 | // } 145 | //} 146 | -------------------------------------------------------------------------------- /test/LightScheduler.c: -------------------------------------------------------------------------------- 1 | 2 | enum 3 | { 4 | MAX_EVENTS = 128, UNUSED = -1 5 | }; 6 | 7 | 8 | typedef struct 9 | { 10 | int id; 11 | Day day; 12 | int minuteOfDay; 13 | int event; 14 | int randomize; 15 | int randomMinutes; 16 | 17 | } ScheduledLightEvent; 18 | 19 | static ScheduledLightEvent eventList[MAX_EVENTS]; 20 | 21 | // from test driven developement in c -------------------------------------------------------------------------------- /test/eeprom_test_ok.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "morse.h" 3 | 4 | char message[255] = {'1','2','3','l','o',' ','o','s','s','i',' ', '1'}; 5 | 6 | int main(void) { 7 | volatile unsigned int i; 8 | volatile unsigned char x; 9 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 10 | 11 | EEPROM_Init(0x50); 12 | 13 | for(i=0; i < 3;i++ ) { 14 | ascii(message[i]); 15 | EEPROM_ByteWrite(i, message[i]); 16 | EEPROM_AckPolling(); 17 | } 18 | 19 | for(i=0; i < 3;i++ ) { 20 | x=EEPROM_RandomRead(i); 21 | ascii(x); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /test/hardware.c: -------------------------------------------------------------------------------- 1 | #include "hardware.h" 2 | 3 | void configure_clock() { 4 | BCSCTL1 |= RSEL0 + RSEL1 + RSEL2; 5 | DCOCTL = DCO0 + DCO1 + DCO2; 6 | BCSCTL2 |= SELM_0 + DIVM_0; 7 | } 8 | 9 | void stop_watchdog() { 10 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 11 | } 12 | 13 | void delay_one_sec() { // it depense on clock speed 14 | __delay_cycles(500000); 15 | } -------------------------------------------------------------------------------- /test/send.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | .__ ____ 4 | ____ ______ ______|__| /_ | 5 | / _ \ / ___/ / ___/| | ______ | | 6 | ( <_> )\___ \ \___ \ | | /_____/ | | 7 | \____//____ >/____ >|__| |___| 8 | \/ \/ 9 | 10 | * Created on: 2012. 6. 3. 11 | * 12 | * 13 | */ 14 | 15 | #include 16 | #include "adf702x.h" 17 | #include "morse.h" 18 | 19 | char message[255] = {'o','s','s', 'i',' ','1',' ',' ',' ',' ',' ',' '}; 20 | int step = 10; 21 | 22 | void configure_clock() { 23 | BCSCTL1 |= RSEL0 + RSEL1 + RSEL2; 24 | DCOCTL = DCO0 + DCO1 + DCO2; 25 | BCSCTL2 |= SELM_0 + DIVM_0; 26 | } 27 | 28 | int main(void) { 29 | volatile unsigned int i; 30 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer 31 | P6DIR |= 0x01; // Set P1.0 to output direction 32 | // configure_clock(); 33 | 34 | adf7020_1_init(); 35 | adf7020_1_sendStart(); 36 | 37 | for(;;) { 38 | for(i=0; i < step-1;i++ ) { 39 | ascii(message[i]); 40 | } 41 | 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /test/tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char message[255] = {'1','2','3','l','o',' ','o','s','s','i',' ', '1'}; 5 | 6 | void test_antenner_deploy(void) { 7 | Ant_Deploy_Init(); 8 | Start_Ant_Deploy_After(5); 9 | } 10 | 11 | void test_tmp101(void) { 12 | // OBC temp sensor 13 | volatile uint16_t temp; 14 | 15 | TMP10x_Init(OBCTEMP_ADDR); 16 | temp = TMP10x_Read(); // C = temp / 0x10 17 | } 18 | 19 | void test_eeprom(void) { 20 | volatile unsigned int i; 21 | volatile unsigned char x; 22 | 23 | EEPROM_Init(EEPROM_ADDR); 24 | 25 | for(i=0; i < 1;i++ ) { 26 | ascii(message[i]); 27 | EEPROM_ByteWrite(i, message[i]); 28 | EEPROM_AckPolling(); 29 | } 30 | 31 | for(i=0; i < 1;i++ ) { 32 | x=EEPROM_RandomRead(i); 33 | ascii(x); 34 | } 35 | } 36 | 37 | void test_panneltemp() 38 | { 39 | volatile uint16_t temp; 40 | volatile uint8_t x; 41 | 42 | PCA9548A_Init(PCA9548A_ADDR); 43 | PCA9548A_SetChannel(PCA9548A_CH_PANELTEMP); 44 | 45 | TMP10x_Init(PANELTEMP_ADDR); 46 | temp = TMP10x_Read(); // C = temp / 0x10 47 | temp = temp+1; 48 | if ((temp/16) > 28) 49 | LED_ON(); 50 | else 51 | LED_OFF(); 52 | } 53 | 54 | void test_payload() 55 | { 56 | PCA9548A_Init(PCA9548A_ADDR); 57 | PCA9548A_SetChannel(2); 58 | 59 | Payload_Init(); 60 | while(1) { 61 | Payload_Light_Off(); 62 | _delay(); 63 | Payload_Light_On(); 64 | _delay(); 65 | } 66 | } 67 | 68 | void test_payload_with_tmp100() 69 | { 70 | volatile uint16_t temp; 71 | volatile uint8_t x; 72 | 73 | PCA9548A_Init(PCA9548A_ADDR); 74 | PCA9548A_SetChannel(PCA9548A_CH_PANELTEMP); 75 | 76 | TMP10x_Init(PANELTEMP_ADDR); 77 | temp = TMP10x_Read(); // C = temp / 0x10 78 | temp = temp+1; 79 | 80 | PCA9548A_Init(PCA9548A_ADDR); 81 | PCA9548A_SetChannel(2); 82 | 83 | Payload_Init(); 84 | 85 | if ((temp/16) > 29) 86 | Payload_Light_On(); 87 | else 88 | Payload_Light_Off(); 89 | _delay(); 90 | 91 | } 92 | 93 | void test_adc(void) 94 | { 95 | volatile uint16_t v; 96 | 97 | v = ADC_Get_Voltage_A1(VSOLAR); 98 | v = v+1; 99 | v = ADC_Get_Voltage_A1(VBUS); 100 | v = v+1; 101 | v = ADC_Get_Voltage_A1(VBAT); 102 | v = v+1; 103 | v = ADC_Get_Voltage_A1(VSUPERCAP); 104 | v = v+1; 105 | 106 | v = ADC_Get_Voltage_A0(SOLAR_CS1); 107 | v = v+1; 108 | v = ADC_Get_Voltage_A0(SOLAR_CS2); 109 | v = v+1; 110 | v = ADC_Get_Voltage_A0(SOLAR_CS3); 111 | v = v+1; 112 | v = ADC_Get_Voltage_A0(SOLAR_CS4); 113 | v = v+1; 114 | v = ADC_Get_Voltage_A0(SOLAR_CS5); 115 | v = v+1; 116 | v = ADC_Get_Voltage_A0(SUN_IN); 117 | v = v+1; 118 | } 119 | 120 | void test_watchdog(void) 121 | { 122 | Watchdog_External_Init(); 123 | } 124 | -------------------------------------------------------------------------------- /tmp10x.c: -------------------------------------------------------------------------------- 1 | #include "24lc256.h" 2 | #include "i2c.h" 3 | 4 | void TMP10x_Init(uint8_t slave_address) 5 | { 6 | InitI2C(slave_address); 7 | } 8 | 9 | 10 | uint16_t TMP10x_Read() 11 | { 12 | while (I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations 13 | I2CReadInit(); 14 | I2CNDAT = 1; // 1 byte should be received 15 | while ((~I2CIFG)&ARDYIFG); // wait untill transmission is finished 16 | return I2CBuffer[0]; 17 | } -------------------------------------------------------------------------------- /tmp10x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tmp10x.h 3 | * 4 | * Created on: 2012. 5. 3. 5 | * Author: donghee 6 | */ 7 | 8 | #ifndef TMP10x_H_ 9 | #define TMP10x_H_ 10 | 11 | #include 12 | #include "i2c.h" 13 | #include "global.h" 14 | 15 | uint16_t TMP10X_Read(void); 16 | void TMP10x_Init(uint8_t slave_address); 17 | 18 | 19 | #endif /* TMP10x_H_ */ 20 | --------------------------------------------------------------------------------