175 lines
3.9 KiB
C
Raw Permalink Normal View History

2020-08-14 18:09:44 +02:00
#include <msp430g2553.h>
#include <intrinsics.h>
2020-08-14 19:34:05 +02:00
#include <stdint.h>
2020-08-14 18:09:44 +02:00
#include <stdbool.h>
2020-08-14 19:45:30 +02:00
/*
* DEBUG_IDLE_BIT is toggled each cycle through the idle loop.
* DEBUG_ADC_BIT is toggled each time the ADC interrupt is fired.
*
* When the COMM_SAMPLE_HOLD_BIT is pulled to high, the next
* conversion result from the ADC is saved and held until the
* COMM_SAMPLE_HOLD_BIT goes to low again.
*
2020-08-27 22:06:45 +02:00
* While the COMM_SAMPLE_HOLD_BIT is pulled to high it is checked
* whether the current ADC value is by SPACE_MARK_THRESHOLD greater
* then the held value. If it is greater, the COMM_RESULT_BIT is set
* to low, otherwise it is set to high.
2020-08-14 19:45:30 +02:00
*
2020-08-27 22:06:45 +02:00
* If COMM_SAMPLE_HOLD_BIT goes to low the COMM_RESULT_BIT is set to
* high.
2020-08-14 19:45:30 +02:00
*/
2020-08-14 20:00:10 +02:00
2020-08-14 19:45:30 +02:00
#define DEBUG
2020-08-14 20:00:10 +02:00
// ADC Channel 3: P1.3
2020-08-14 19:34:05 +02:00
#define DEBUG_PORT P1OUT
#define DEBUG_PORT_DIR P1DIR
2020-08-14 20:00:10 +02:00
#define DEBUG_IDLE_BIT BIT7 // P1.7
#define DEBUG_ADC_BIT BIT6 // P1.6
2020-08-14 18:09:44 +02:00
2020-08-14 19:34:05 +02:00
#define COMM_PORT_OUT P2OUT
#define COMM_PORT_IN P2IN
2020-08-27 22:06:45 +02:00
#define COMM_PORT_REN P2REN
2020-08-14 19:34:05 +02:00
#define COMM_PORT_DIR P2DIR
2020-08-14 20:00:10 +02:00
#define COMM_RESULT_BIT BIT2 // P2.2
#define COMM_SAMPLE_HOLD_BIT BIT3 // P2.3
2020-08-14 18:09:44 +02:00
2020-08-14 19:55:40 +02:00
// derived from the calculation in mbus-converter.ods
// assumes a 25Ohm shunt resistor and a 10mA swing
2020-08-14 19:34:05 +02:00
#define SPACE_MARK_THRESHOLD 100
2020-08-27 22:06:45 +02:00
// SPI debug codes
#define DBG_START 0xffffffff
#define DBG_HOLD 0x01000000
#define DBG_SAMPLE 0x02000000
#define DBG_RX_SLOPE 0x04000000
// 32bit-value to transmit via SPI
volatile uint32_t spiTxBuf = 0;
// ISR for SPI transmitter
__attribute__((interrupt(USCIAB0TX_VECTOR)))
void spiTxIsr(void) {
static uint8_t oc = 0;
oc++;
if (oc < 4) {
UCA0TXBUF = (uint8_t)((spiTxBuf >> (8 * oc)) & 0x00ff);
} else {
IE2 &= ~UCA0TXIE;
oc = 0;
}
}
void writeSpi(uint32_t m) {
spiTxBuf = m;
UCA0TXBUF = (uint8_t)(spiTxBuf & 0x00ff);
IE2 |= UCA0TXIE;
}
2020-08-14 19:34:05 +02:00
// ISR to read and process result from adc
__attribute__((interrupt(ADC10_VECTOR)))
2020-08-27 22:10:00 +02:00
void adcIsr(void) {
2020-08-14 19:34:05 +02:00
static uint16_t holdValue = 0;
static bool holdFlag = false;
uint16_t currentValue = ADC10MEM;
if ((COMM_PORT_IN & COMM_SAMPLE_HOLD_BIT)) {
if (! holdFlag) {
holdValue = currentValue;
holdFlag = true;
2020-08-27 22:06:45 +02:00
writeSpi(DBG_HOLD | holdValue);
} else {
if (currentValue > (holdValue + SPACE_MARK_THRESHOLD)) {
COMM_PORT_OUT &= ~COMM_RESULT_BIT;
// writeSpi(DBG_RX_SLOPE | currentValue);
} else {
COMM_PORT_OUT |= COMM_RESULT_BIT;
}
2020-08-14 19:34:05 +02:00
}
} else {
2020-08-27 22:06:45 +02:00
if (holdFlag) {
holdFlag = false;
2020-08-27 10:26:07 +02:00
COMM_PORT_OUT |= COMM_RESULT_BIT;
2020-08-27 22:06:45 +02:00
writeSpi(DBG_SAMPLE);
2020-08-14 19:34:05 +02:00
}
}
2020-08-14 19:45:30 +02:00
#ifdef DEBUG
2020-08-14 19:34:05 +02:00
DEBUG_PORT ^= DEBUG_ADC_BIT;
2020-08-14 19:45:30 +02:00
#endif // DEBUG
2020-08-14 19:34:05 +02:00
}
void setup() {
2020-08-14 18:09:44 +02:00
WDTCTL = WDTPW | WDTHOLD;
__disable_interrupt();
// highest possible system clock
DCOCTL = DCO0 | DCO1 | DCO2;
BCSCTL1 = XT2OFF | RSEL0 | RSEL1 | RSEL2 | RSEL3;
BCSCTL2 = 0;
BCSCTL3 = 0;
2020-08-14 19:34:05 +02:00
// debug port configuration, obviously
2020-08-14 19:45:30 +02:00
#ifdef DEBUG
2020-08-14 19:34:05 +02:00
DEBUG_PORT_DIR |= DEBUG_IDLE_BIT | DEBUG_ADC_BIT;
DEBUG_PORT &= ~(DEBUG_IDLE_BIT | DEBUG_ADC_BIT);
2020-08-14 19:45:30 +02:00
#endif // DEBUG
2020-08-14 18:09:44 +02:00
2020-08-14 19:34:05 +02:00
// communication
COMM_PORT_DIR |= COMM_RESULT_BIT;
2020-08-27 22:06:45 +02:00
COMM_PORT_DIR &= ~COMM_SAMPLE_HOLD_BIT;
COMM_PORT_REN |= COMM_SAMPLE_HOLD_BIT;
COMM_PORT_OUT &= ~COMM_SAMPLE_HOLD_BIT;
2020-08-27 10:26:07 +02:00
COMM_PORT_OUT |= COMM_RESULT_BIT;
2020-08-14 18:09:44 +02:00
2020-08-14 19:34:05 +02:00
// adc
2020-08-27 22:06:45 +02:00
ADC10CTL0 = SREF_1 | REFON | ADC10ON | ADC10IE | MSC;
2020-08-14 19:34:05 +02:00
ADC10CTL1 = INCH_3 | CONSEQ_2;
ADC10AE0 = BIT3;
2020-08-14 18:09:44 +02:00
2020-08-27 22:06:45 +02:00
// spi
UCA0CTL1 = UCSWRST | UCSSEL_2;
UCA0CTL0 = UCMST | UCSYNC;
UCA0BR0 = 8;
UCA0BR1 = 0;
P1SEL |= BIT1 | BIT2 | BIT4;
P1SEL2 |= BIT1 | BIT2 | BIT4;
UCA0CTL1 &= ~UCSWRST;
2020-08-14 18:09:44 +02:00
__enable_interrupt();
2020-08-14 19:34:05 +02:00
// start the adc
ADC10CTL0 |= ENC | ADC10SC;
}
void loop() {
2020-08-14 19:45:30 +02:00
#ifdef DEBUG
2020-08-14 19:34:05 +02:00
DEBUG_PORT ^= DEBUG_IDLE_BIT;
2020-08-14 19:45:30 +02:00
#endif // DEBUG
2020-08-14 19:34:05 +02:00
}
int main() {
setup();
2020-08-27 22:06:45 +02:00
writeSpi(DBG_START);
2020-08-14 18:09:44 +02:00
while (1) {
2020-08-14 19:34:05 +02:00
loop();
2020-08-14 18:09:44 +02:00
}
}