Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: azonenberg/starshipraider
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c24b89f73b5f
Choose a base ref
...
head repository: azonenberg/starshipraider
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d04d4ecd573f
Choose a head ref
  • 4 commits
  • 3 files changed
  • 1 contributor

Commits on Jul 7, 2020

  1. Updated submodules

    azonenberg committed Jul 7, 2020
    Copy the full SHA
    35bb23a View commit details
  2. Copy the full SHA
    00dc6af View commit details
  3. Copy the full SHA
    d900f71 View commit details
  4. Copy the full SHA
    d04d4ec View commit details
Showing with 200 additions and 39 deletions.
  1. +6 −0 firmware/MEAD/AMG240160P.h
  2. +193 −38 firmware/MEAD/main.cpp
  3. +1 −1 firmware/stm32-cpp
6 changes: 6 additions & 0 deletions firmware/MEAD/AMG240160P.h
Original file line number Diff line number Diff line change
@@ -51,6 +51,12 @@ class AMG240160P : public CharacterDevice
void ClearScreen();
void UpdateScreen();

void ClearRow(uint8_t row)
{
for(int i=0; i<AMG240160P_FRAMEBUFFER_COLS; i++)
m_framebuffer[row][i] = ' ';
}

//Raw framebuffer access
char m_framebuffer[AMG240160P_FRAMEBUFFER_ROWS][AMG240160P_FRAMEBUFFER_COLS];

231 changes: 193 additions & 38 deletions firmware/MEAD/main.cpp
Original file line number Diff line number Diff line change
@@ -34,17 +34,31 @@
#include <peripheral/I2C.h>
#include <peripheral/Timer.h>
#include <util/StringBuffer.h>
#include <string.h>
#include <stdlib.h>
#include "AT30TS74.h"
#include "AMG240160P.h"
#include "DAC60508.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entry point
//Global peripherals
UART* g_uart;
DAC60508* g_dac;
AMG240160P* g_display;
AT30TS74* g_leftTemp;
AT30TS74* g_rightTemp;

//Channel configuration
uint8_t g_channelAttenuations[8];
uint16_t g_channelThresholds[8] = {0};

//UART stuff
UART* g_uart;
void SetAttenuation(uint8_t channel, uint8_t atten);
void SetThreshold(uint8_t channel, uint16_t threshold);
void UpdateChannelInfoText(uint8_t channel);

void UpdateSensors(AT30TS74* left, AT30TS74* right, AMG240160P* display);
void ProcessCommand(const char* cmd);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entry point

//When possible, long-lived stuff here should be declared static.
//This puts them in .bss instead of stack, and enables better accounting of memory usage
@@ -71,73 +85,214 @@ int main()
static GPIOPin spi_mosi(&GPIOB, 5, GPIOPin::MODE_PERIPHERAL, 0);
static SPI spi(&SPI1, true, 4);

//Set up timer with 1us ticks
static Timer timer(&TIM1, Timer::FEATURE_ADVANCED, 48);

//Set up I2C.
//Prescale divide by 8 (6 MHz, 166.6 ns/tick)
//Divide I2C clock by 16 after that to get 375 kHz
static GPIOPin i2c_sda( &GPIOB, 7, GPIOPin::MODE_PERIPHERAL, 1);
static GPIOPin i2c_scl( &GPIOB, 6, GPIOPin::MODE_PERIPHERAL, 1);
static I2C i2c(&I2C1, 8, 8);

//Wait 50ms for peripherals to fully power up before talking to them
timer.Sleep(50000, true);
//Set up timer with 1us ticks
static Timer timer(&TIM1, Timer::FEATURE_ADVANCED, 48);

//Wait 250 ms for everything to power up fully before doing anything else
for(int i=0; i<250; i++)
timer.Sleep(1000, true);

//Set up temperature sensors
AT30TS74 temp_right(&i2c, 0x90);
AT30TS74 temp_left(&i2c, 0x92);
static AT30TS74 temp_right(&i2c, 0x90);
static AT30TS74 temp_left(&i2c, 0x92);
g_leftTemp = &temp_left;
g_rightTemp = &temp_right;

//Set up DAC
static GPIOPin dac_cs_n(&GPIOA, 15, GPIOPin::MODE_OUTPUT);
DAC60508 dac(&spi, &dac_cs_n);
static DAC60508 dac(&spi, &dac_cs_n);
g_dac = &dac;

//Set up LCD
static GPIOPin lcd_cs_n(&GPIOA, 0, GPIOPin::MODE_OUTPUT);
static GPIOPin lcd_rst_n(&GPIOA, 2, GPIOPin::MODE_OUTPUT);
static GPIOPin lcd_ctl_data(&GPIOA, 3, GPIOPin::MODE_OUTPUT);
AMG240160P lcd(&spi, &lcd_cs_n, &lcd_rst_n, &lcd_ctl_data, &timer);
static AMG240160P lcd(&spi, &lcd_cs_n, &lcd_rst_n, &lcd_ctl_data, &timer);
g_display = &lcd;

//Add initial channel names
//Initial setup
for(int i=0; i<8; i++)
{
//Default channels to 1x probe, 500 mV threshold
g_channelAttenuations[i] = 1;
SetThreshold(i, 500);

//Initial default channel names
lcd.MoveTo(0, i*2);
lcd.Printf("CH%d", i);

lcd.MoveTo(0, i*2 + 1);
lcd.Printf(" 1.65V x10");
//Infobox text
UpdateChannelInfoText(i);
}

//Initialize the DAC
dac.SetVoltage(7, 500);
//Push the updates to the screen
lcd.UpdateScreen();

//Main loop
static char cmd[128] = {0};
uint8_t icmd = 0;
while(true)
{
//Refresh sensors and push to the display
UpdateSensors(&temp_left, &temp_right, &lcd);
lcd.UpdateScreen();
//Process input
char ch = g_uart->BlockingRead();

if( (ch == '\r') || (ch == '\n') )
{
ProcessCommand(cmd);
icmd = 0;
memset(cmd, 0, sizeof(cmd));
continue;
}

cmd[icmd] = ch;
icmd ++;

//Wait 500ms
for(int i=0; i<500; i++)
timer.Sleep(1000, true);
//Discard too-long inputs
if(icmd == 127)
{
icmd = 0;
memset(cmd, 0, sizeof(cmd));
continue;
}

//No input? wait a bit
timer.Sleep(1000, true);
}

return 0;
}

void UpdateSensors(AT30TS74* left, AT30TS74* right, AMG240160P* display)
/**
@brief Executes a command from the UART
Commands are formatted as follows, and terminated by a newline.
Opcode (one lowercase letter)
Channel number (one ASCII digit)
Arguments as needed
Opcodes:
n Set display name of channel (argument = up to 20 chars of display name)
a Set channel attenuation (argument = attenuation)
v Set channel voltage threshold (argument = threshold in mV)
t Read temperature sensor (ch0 = left, ch1 = right)
*/
void ProcessCommand(const char* cmd)
{
uint8_t temp;
uint8_t temp_frac;

//Left side
display->MoveTo(13, 0);
left->GetTemperature(temp, temp_frac);
display->Printf("%d.%02d C", temp, temp_frac * 100 / 256);

//Right side
display->MoveTo(13, 15);
right->GetTemperature(temp, temp_frac);
display->Printf("%d.%02d C", temp, temp_frac * 100 / 256);
//All commands require a channel number. Discard anything invalid.
uint8_t channel_num = cmd[1] - '0';
if(channel_num >= 8)
return;

switch(cmd[0])
{
//Set display name
case 'n':
{
//Make sure name fits on screen (discard anything too long)
const char* name = cmd + 2;
if(strlen(name) > 20)
break;

//Print it
uint8_t row = channel_num*2;
g_display->ClearRow(row);
g_display->MoveTo(0, row);
g_display->Printf("%s", name);

g_display->UpdateScreen();
}
break;

//Set channel attenuation
case 'a':
SetAttenuation(channel_num, atoi(cmd+2));
UpdateChannelInfoText(channel_num);
g_display->UpdateScreen();
break;

//Set channel voltage threshold
case 'v':
SetThreshold(channel_num, atoi(cmd+2));
UpdateChannelInfoText(channel_num);
g_display->UpdateScreen();

//Read temperature sensor
case 't':
{
uint8_t temp;
uint8_t temp_frac;
if(channel_num == 0)
g_leftTemp->GetTemperature(temp, temp_frac);
else
g_rightTemp->GetTemperature(temp, temp_frac);

g_uart->Printf("%d.%02d\n", temp, temp_frac * 100 / 256);
}

//ignore unknown commands
default:
break;
}
}

/**
@brief Updates the display with the info text for a channel
*/
void UpdateChannelInfoText(uint8_t channel)
{
uint8_t row = channel*2 + 1;

g_display->ClearRow(row);
g_display->MoveTo(2, row);
g_display->Printf(
"%d.%03dV x%d",
g_channelThresholds[channel] / 1000,
g_channelThresholds[channel] % 1000,
g_channelAttenuations[channel]);
}

/**
@brief Sets the attenuation for a channel
*/
void SetAttenuation(uint8_t channel, uint8_t atten)
{
if(channel >= 8)
return;

g_channelAttenuations[channel] = atten;

//Re-set the threshold to correct for the new attenuation
SetThreshold(channel, g_channelThresholds[channel]);
}

/**
@brief Sets the threshold for a channel, in mV
*/
void SetThreshold(uint8_t channel, uint16_t threshold)
{
if(channel >= 8)
return;

g_channelThresholds[channel] = threshold;

//Scale DAC voltage by probe attenuation
threshold /= g_channelAttenuations[channel];

//Map of left-right channel numbers to netlist channels
//(CH0 in the schematic is not the leftmost one)
static uint8_t physical_channel_mapping[8] = { 7, 6, 3, 2, 1, 0, 5, 4 };
channel = physical_channel_mapping[channel];

//Map of netlist channel numbers to DAC channels
static uint8_t dac_channel_mapping[8] = { 7, 6, 0, 1, 4, 5, 2, 3 };
channel = dac_channel_mapping[channel];

g_dac->SetVoltage(channel, threshold);
}
2 changes: 1 addition & 1 deletion firmware/stm32-cpp
Submodule stm32-cpp updated 1 files
+4 −4 src/util/FIFO.h