it finally jumps!

added some PIO assembly to talk to the ch446qs
This commit is contained in:
Kevin Santo Cappuccio 2023-06-09 13:22:05 -07:00
parent bb30756e71
commit 5795ceb838
15 changed files with 1059 additions and 558 deletions

View File

@ -1,47 +1,12 @@
bridges
{
1-2,
30-4,
50-60,
17-38,
9-10,
16-12,
D13-D1,
D0-1,
A1-5,
D13-A7,
AREF-A1,
20-33,
10-41,
D10-D11,
D11-D12,
1-11,
D2-33,
D9,18,
D5-44,
A2-33,
25-55,
7-27,
6-26,
5-25,
4-24,
3-28,
2-29,
8-23,
D3-18,
D4-19,
A7-22,
A6-21,
10-33,
23-57,
}
special functions //these are connected first so DNIs will be applied to all the nets
{
19-GND,
52-GND,
53-GND,
11-SUPPLY_5V,
D10-SUPPLY_3V3,
6-I_P,
I_P-I_N,
20-SUPPLY_3V3,
58-GND,
}

View File

@ -0,0 +1,49 @@
bridges
{
1-2,
30-4,
50-60,
17-38,
9-10,
16-12,
D13-D1,
D0-1,
A1-5,
D13-A7,
AREF-A1,
20-33,
10-41,
D10-D11,
D11-D12,
1-11,
D2-33,
D9,18,
D5-44,
A2-33,
25-55,
7-27,
6-26,
5-25,
4-24,
3-28,
2-29,
8-23,
D3-18,
D4-19,
A7-22,
A6-21,
41-50,
36-43,
}
special functions //these are connected first so DNIs will be applied to all the nets
{
19-GND,
52-GND,
53-GND,
11-SUPPLY_5V,
D10-SUPPLY_3V3,
6-I_P,
I_P-I_N,
}

View File

@ -1,18 +0,0 @@
bridges
{
}
special functions //these are connected first so DNIs will be applied to all the nets
{
60-GND,
59-GND,
29-SUPPLY_5V,
30-SUPPLY_5V,
16-SUPPLY_3V3,
15-SUPPLY_3V3,
1-DAC0_5V,
2-DAC0_5V,
31-DAC1_8V,
32-DAC1_8V,
}

View File

@ -0,0 +1,249 @@
#include "CH446Q.h"
#include "MatrixStateRP2040.h"
#include "NetsToChipConnections.h"
#include "LEDs.h"
#include "Peripherals.h"
#include "JumperlessDefinesRP2040.h"
// #include <SPI.h>
// #include "pico/stdlib.h"
#include "hardware/pio.h"
// #include "hardware/clocks.h"
// #include "ch446.pio.h"
#include "spi.pio.h"
#include "pio_spi.h"
// #include "ch446_spi.pio.h"
int chipToPinArray[12] = {CS_A, CS_B, CS_C, CS_D, CS_E, CS_F, CS_G, CS_H, CS_I, CS_J, CS_K, CS_L};
PIO pio = pio0;
uint sm = pio_claim_unused_sm(pio, true);
volatile int chipSelect = 0;
volatile uint32_t irq_flags = 0;
void isrFromPio(void)
{
// noInterrupts();
// pinMode(DATAPIN, OUTPUT);
// digitalWriteFast(DATAPIN, LOW);
switch (chipSelect)
{
case CHIP_A:
{
digitalWriteFast(CS_A, HIGH);
break;
}
case CHIP_B:
{
digitalWriteFast(CS_B, HIGH);
break;
}
case CHIP_C:
{
digitalWriteFast(CS_C, HIGH);
break;
}
case CHIP_D:
{
digitalWriteFast(CS_D, HIGH);
break;
}
case CHIP_E:
{
digitalWriteFast(CS_E, HIGH);
break;
}
case CHIP_F:
{
digitalWriteFast(CS_F, HIGH);
break;
}
case CHIP_G:
{
digitalWriteFast(CS_G, HIGH);
break;
}
case CHIP_H:
{
digitalWriteFast(CS_H, HIGH);
break;
}
case CHIP_I:
{
digitalWriteFast(CS_I, HIGH);
break;
}
case CHIP_J:
{
digitalWriteFast(CS_J, HIGH);
break;
}
case CHIP_K:
{
digitalWriteFast(CS_K, HIGH);
break;
}
case CHIP_L:
{
digitalWriteFast(CS_L, HIGH);
break;
}
}
// Serial.print(chipSelect);
// return;
delayMicroseconds(1);
digitalWriteFast(CS_A, LOW);
digitalWriteFast(CS_B, LOW);
digitalWriteFast(CS_C, LOW);
digitalWriteFast(CS_D, LOW);
digitalWriteFast(CS_E, LOW);
digitalWriteFast(CS_F, LOW);
digitalWriteFast(CS_G, LOW);
digitalWriteFast(CS_H, LOW);
digitalWriteFast(CS_I, LOW);
digitalWriteFast(CS_J, LOW);
digitalWriteFast(CS_K, LOW);
digitalWriteFast(CS_L, LOW);
irq_flags = pio0_hw->irq;
pio_interrupt_clear(pio, PIO0_IRQ_0);
hw_clear_bits(&pio0_hw->irq, irq_flags);
// interrupts();
}
void initCH446Q(void)
{
uint dat = 19;
uint clk = 18;
uint cs = 7;
irq_add_shared_handler(PIO0_IRQ_0, isrFromPio, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
irq_set_enabled(PIO0_IRQ_0, true);
uint offset = pio_add_program(pio, &spi_ch446_multi_cs_program);
// uint offsetCS = pio_add_program(pio, &spi_ch446_cs_handler_program);
Serial.print("offset: ");
Serial.println(offset);
pio_spi_ch446_multi_cs_init(pio, sm, offset, 8, 16, 0, 1, clk, dat);
// pio_spi_ch446_cs_handler_init(pio, smCS, offsetCS, 256, 1, 8, 20, 6);
// pinMode(CS_A, OUTPUT);
// digitalWrite(CS_A, HIGH);
pinMode(CS_A, OUTPUT);
pinMode(CS_B, OUTPUT);
pinMode(CS_C, OUTPUT);
pinMode(CS_D, OUTPUT);
pinMode(CS_E, OUTPUT);
pinMode(CS_F, OUTPUT);
pinMode(CS_G, OUTPUT);
pinMode(CS_H, OUTPUT);
pinMode(CS_I, OUTPUT);
pinMode(CS_J, OUTPUT);
pinMode(CS_K, OUTPUT);
pinMode(CS_L, OUTPUT);
digitalWrite(CS_A, LOW);
digitalWrite(CS_B, LOW);
digitalWrite(CS_C, LOW);
digitalWrite(CS_D, LOW);
digitalWrite(CS_E, LOW);
digitalWrite(CS_F, LOW);
digitalWrite(CS_G, LOW);
digitalWrite(CS_H, LOW);
digitalWrite(CS_I, LOW);
digitalWrite(CS_J, LOW);
digitalWrite(CS_K, LOW);
digitalWrite(CS_L, LOW);
pinMode(RESETPIN, OUTPUT);
digitalWrite(RESETPIN, HIGH);
delay(10);
digitalWrite(RESETPIN, LOW);
}
void sendAllPaths(void) // should we sort them by chip? for now, no
{
for (int i = 0; i < numberOfPaths; i++)
{
sendPath(i, 1);
delay(1200);
}
for (int i = numberOfPaths; i >= 0; i--)
{
sendPath(i, 0);
delay(800);
}
}
void sendPath(int i, int setOrClear)
{
uint32_t chAddress = 0;
int chipToConnect = 0;
int chYdata = 0;
int chXdata = 0;
for (int chip = 0; chip < 4; chip++)
{
if (path[i].chip[chip] != -1)
{
chipSelect = path[i].chip[chip];
chipToConnect = path[i].chip[chip];
for (int xy = 0; xy < 6; xy++)
{
if (path[i].x[xy] == -1 || path[i].y[xy] == -1)
{
continue;
}
lightUpNet(path[i].net, path[i].node1, setOrClear);
lightUpNet(path[i].net, path[i].node2, setOrClear);
chYdata = path[i].y[chip];
chXdata = path[i].x[chip];
chYdata = chYdata << 5;
chYdata = chYdata & 0b11100000;
chXdata = chXdata << 1;
chXdata = chXdata & 0b00011110;
chAddress = chYdata | chXdata;
if (setOrClear == 1)
{
chAddress = chAddress | 0b00000001; // this last bit determines whether we set or unset the path
}
chAddress = chAddress << 24;
// delayMicroseconds(50);
delayMicroseconds(30);
pio_sm_put(pio, sm, chAddress);
delayMicroseconds(30);
}
}
}
}
void createXYarray(void)
{
}

View File

@ -0,0 +1,12 @@
#ifndef CH446Q_H
#define CH446Q_H
void initCH446Q(void);
void sendAllPaths(void); // should we sort them by chip? for now, no
void sendPath(int path, int setOrClear = 1);
void createXYarray(void);
#endif

View File

@ -34,14 +34,15 @@
#define CS_F 11
#define CS_G 12
#define CS_H 13
#define CS_I 20
#define CS_J 21
#define CS_K 22
#define CS_L 23
#define DATAPIN 14
#define DATAPIN 19
#define RESETPIN 24
#define CLKPIN 15
#define CLKPIN 18
#define UART0_TX 0
#define UART0_RX 1

View File

@ -5,9 +5,14 @@
Adafruit_NeoPixel leds(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
rgbColor netColors[MAX_NETS] = {0};
uint8_t saturation = 254;
uint8_t brightness = BRIGHTNESS;
void initLEDs(void)
{
pinMode(LED_PIN, OUTPUT);
leds.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
leds.show(); // Turn OFF all pixels ASAP
leds.setBrightness(BRIGHTNESS);
@ -43,189 +48,323 @@ void rainbowy(int saturation, int brightness, int wait)
}
}
void assignNetColors (void)
void assignNetColors(void)
{
//numberOfNets = 60;
// numberOfNets = 60;
uint16_t colorDistance = 255 / numberOfNets;
/* rgbColor specialNetColors[8] =
{0x000000,
0x00FF80,
0xFF4114,
0xFF0040,
0xFF7800,
0xFF4078,
0xFFC8C8,
0xC8FFC8};
*/
rgbColor specialNetColors[8] =
{{00, 00, 00},
{0x00, 0xFF, 0x30},
{0xFF, 0x41, 0x14},
{0xFF, 0x10, 0x40},
{0xFF, 0x78, 0x00},
{0xFF, 0x40, 0x78},
{0xFF, 0xC8, 0xC8},
{0xC8, 0xFF, 0xC8}};
rgbColor railColors[4] =
{
{0xFF, 0x41, 0x14},
{0x00, 0xFF, 0x30},
{0xFF, 0x00, 0x40},
{0x00, 0xFF, 0x30}};
uint16_t colorDistance = 0xffff / numberOfNets;
uint32_t netColors[numberOfNets];
uint32_t specialNetColors[8] =
{0x000000,
0x00FF80,
0xFF4114,
0xFF0040,
0xFF7800,
0xFF4078,
0xFFC8C8,
0xC8FFC8};
uint32_t railColors[4] =
{
0xFF4114,
0x00FF80,
0xFF0040,
0x00FF80};
Serial.print("colorDistance: ");
Serial.print(colorDistance);
Serial.print("\n\r");
Serial.print("numberOfNets: ");
Serial.print(numberOfNets);
Serial.print("colorDistance: ");
Serial.print(colorDistance);
Serial.print("\n\r");
Serial.print("numberOfNets: ");
Serial.print(numberOfNets);
Serial.print("\n\rassigning net colors\n\r");
for (int i = 0; i < 8; i++)
{
netColors[i] = specialNetColors[i];
net[i].color = netColors[i];
Serial.print("\n\r");
Serial.print(net[i].name);
Serial.print("\t");
Serial.print(net[i].color, HEX);
}
for (int i = 0; i < 5; i++)
{
leds.setPixelColor(railsToPixelMap[0][i], railColors[0] ); //top positive rail
leds.setPixelColor(railsToPixelMap[1][i], railColors[1]); //top negative rail
leds.setPixelColor(railsToPixelMap[2][i], railColors[2]); //bottom positive rail
leds.setPixelColor(railsToPixelMap[3][i], railColors[3]); //bottom negative rail
//leds.show();
}
delay(1000);
int skipSpecialColors = 0;
for(int i = 8; i < numberOfNets; i++)
for (int i = 0; i < 8; i++)
{
for (int j = 1; j < 8; j++)
{
if (leds.gamma32(leds.ColorHSV(colorDistance * (j + skipSpecialColors),255,200) - leds.ColorHSV(specialNetColors[j],255,200)) < (colorDistance))
{
Serial.print("\n\rskipping color: ");
Serial.print(colorDistance * (j + skipSpecialColors),HEX);
Serial.print("\n\r");
Serial.print(i);
Serial.print("\t");
Serial.print(leds.gamma32(leds.ColorHSV(colorDistance * (j + skipSpecialColors),255,200)),HEX);
Serial.print(" == ");
Serial.print(leds.gamma32(leds.ColorHSV(specialNetColors[j],255,200)),HEX);
Serial.print("\t");
Serial.print(j);
Serial.print("\n\r");
skipSpecialColors++;
colorDistance = 0xffff / (numberOfNets + skipSpecialColors);
Serial.print("colorDistance: ");
Serial.print(colorDistance,HEX);
Serial.print("\n\r");
} else if (leds.gamma32(leds.ColorHSV(colorDistance * (j + skipSpecialColors),255,200) - leds.ColorHSV(specialNetColors[j],255,200)) < (colorDistance))
{
Serial.print("\n\rskipping color: ");
Serial.print(colorDistance * (j + skipSpecialColors),HEX);
Serial.print("\n\r");
Serial.print(leds.gamma32(leds.ColorHSV(colorDistance * (j + skipSpecialColors),255,200)),HEX);
Serial.print(" == ");
Serial.print(leds.gamma32(leds.ColorHSV(specialNetColors[j],255,200)),HEX);
Serial.print("\n\r");
skipSpecialColors++;
colorDistance = 0xffff / (numberOfNets + skipSpecialColors);
Serial.print("colorDistance: ");
Serial.print(colorDistance,HEX);
Serial.print("\n\r");
} else {
netColors[i] = leds.gamma32(leds.ColorHSV(colorDistance * (i + skipSpecialColors),255,200));
}
}
//leds.setPixelColor(i, netColors[i]);
hsvColor netHsv = RgbToHsv(specialNetColors[i]);
netColors[i] = specialNetColors[i];
net[i].color = netColors[i];
Serial.print("\n\r");
Serial.print(net[i].name);
Serial.print("\t");
Serial.print(net[i].color,HEX);
Serial.print(net[i].color.r, HEX);
Serial.print("\t");
Serial.print(net[i].color.g, HEX);
Serial.print("\t");
Serial.print(net[i].color.b, HEX);
Serial.print("\t\t");
Serial.print(netHsv.h);
Serial.print("\t");
Serial.print(netHsv.s);
Serial.print("\t");
Serial.print(netHsv.v);
}
//leds.show();
//delay(100000);
for (int i = 0; i < numberOfNets; i++)
{
if (net[i].nodes[1] != 0 && net[i].nodes[1] < 62)
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
{
for (int j = 0; j < MAX_NODES; j++)
{
if (net[i].nodes[j] == 0)
uint32_t color = packRgb(railColors[j].r, railColors[j].g, railColors[j].b);
leds.setPixelColor(railsToPixelMap[j][i], color); // top positive rail
}
/*
leds.setPixelColor(railsToPixelMap[1][i], railColors[1]); // top negative rail
leds.setPixelColor(railsToPixelMap[2][i], railColors[2]); // bottom positive rail
leds.setPixelColor(railsToPixelMap[3][i], railColors[3]); // bottom negative rail
*/
}
leds.show();
delay(1);
int skipSpecialColors = 0;
uint8_t hue = 0;
for (int i = 8; i < numberOfNets; i++)
{
uint8_t r = 0;
uint8_t g = 0;
uint8_t b = 0;
int foundColor = 0;
for (uint8_t hueScan = ((i - 8) * colorDistance); hueScan < 255; hueScan += (colorDistance))
{
for (int k = 0; k < 8; k++)
{
hsvColor snColor = RgbToHsv(specialNetColors[k]);
if (hueScan > snColor.h)
{
if (hueScan - snColor.h < colorDistance)
{
skipSpecialColors = 1;
// Serial.print("skipping special color: ");
// Serial.print(k);
// continue;
break;
}
}
else if (snColor.h - hueScan < colorDistance)
{
skipSpecialColors = 1;
// continue;
// Serial.print("skipping special color: ");
// Serial.print(k);
break;
}
else if (hueScan - hue < colorDistance)
{
skipSpecialColors = 1;
// continue;
// Serial.print("skipping special color: ");
// Serial.print(k);
break;
}
}
if (skipSpecialColors == 1)
{
skipSpecialColors = 0;
continue;
}
else
{
foundColor = 1;
hue = hueScan;
break;
}
if (net[i].nodes[j] < 62)
{
leds.setPixelColor(nodesToPixelMap[net[i].nodes[j]], net[i].color);
}
// hue = hueScan;
}
if (foundColor == 0)
{
}
leds.show();
delay(1200);
}
hsvColor netHsv = {hue, saturation, brightness};
netColors[i] = HsvToRgb(netHsv);
// leds.setPixelColor(i, netColors[i]);
net[i].color.r = netColors[i].r;
net[i].color.g = netColors[i].g;
net[i].color.b = netColors[i].b;
Serial.print("\n\r");
Serial.print(net[i].name);
Serial.print("\t\t");
Serial.print(net[i].color.r, HEX);
Serial.print("\t");
Serial.print(net[i].color.g, HEX);
Serial.print("\t");
Serial.print(net[i].color.b, HEX);
Serial.print("\t\t");
Serial.print(hue);
Serial.print("\t");
Serial.print(saturation);
Serial.print("\t");
Serial.print(brightness);
}
}
uint32_t packRgb(uint8_t r, uint8_t g, uint8_t b)
{
return (uint32_t)r << 16 | (uint32_t)g << 8 | b;
}
void lightUpNet(int netNumber, int node, int onOff)
{
if (net[netNumber].nodes[1] != 0 && net[netNumber].nodes[1] < 62)
{
for (int j = 0; j < MAX_NODES; j++)
{
if (net[netNumber].nodes[j] == 0)
{
break;
}
if (net[netNumber].nodes[j] < 62)
{
if (net[netNumber].nodes[j] == node || node == -1)
{
if (onOff == 1)
{
uint32_t color = packRgb(net[netNumber].color.r, net[netNumber].color.g, net[netNumber].color.b);
leds.setPixelColor(nodesToPixelMap[net[netNumber].nodes[j]], color);
}
else
{
leds.setPixelColor(nodesToPixelMap[net[netNumber].nodes[j]], 0);
}
}
}
}
leds.show();
delay(1);
}
}
void showNets(void)
{
for (int i = 0; i < numberOfNets; i++)
for (int i = 0; i < numberOfNets; i++)
{
for (int j = 0; j < numberOfPaths; j++)
{
leds.setPixelColor(bbPixelToNodesMap[net[i].nodes[j]], net[i].color);
uint32_t color = packRgb(net[i].color.r, net[i].color.g, net[i].color.b);
leds.setPixelColor(bbPixelToNodesMap[net[i].nodes[j]], color);
}
}
leds.show();
}
rgbColor HsvToRgb(hsvColor hsv)
{
rgbColor rgb;
unsigned char region, p, q, t;
unsigned int h, s, v, remainder;
if (hsv.s == 0)
{
rgb.r = hsv.v;
rgb.g = hsv.v;
rgb.b = hsv.v;
return rgb;
}
// converting to 16 bit to prevent overflow
h = hsv.h;
s = hsv.s;
v = hsv.v;
region = h / 43;
remainder = (h - (region * 43)) * 6;
p = (v * (255 - s)) >> 8;
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
switch (region)
{
case 0:
rgb.r = v;
rgb.g = t;
rgb.b = p;
break;
case 1:
rgb.r = q;
rgb.g = v;
rgb.b = p;
break;
case 2:
rgb.r = p;
rgb.g = v;
rgb.b = t;
break;
case 3:
rgb.r = p;
rgb.g = q;
rgb.b = v;
break;
case 4:
rgb.r = t;
rgb.g = p;
rgb.b = v;
break;
default:
rgb.r = v;
rgb.g = p;
rgb.b = q;
break;
}
return rgb;
}
hsvColor RgbToHsv(rgbColor rgb)
{
hsvColor hsv;
unsigned char rgbMin, rgbMax;
rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
hsv.v = rgbMax;
if (hsv.v == 0)
{
hsv.h = 0;
hsv.s = 0;
return hsv;
}
hsv.s = 255 * ((long)(rgbMax - rgbMin)) / hsv.v;
if (hsv.s == 0)
{
hsv.h = 0;
return hsv;
}
if (rgbMax == rgb.r)
hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
else if (rgbMax == rgb.g)
hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
else
hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
return hsv;
}

View File

@ -4,13 +4,30 @@
#include <Arduino.h>
#include "JumperlessDefinesRP2040.h"
#include "Adafruit_NeoPixel.h"
#include "NetsToChipConnections.h"
#define LED_PIN 25
#define LED_COUNT 160
#define BRIGHTNESS 100
#define BRIGHTNESS 220
extern Adafruit_NeoPixel leds;
typedef struct rgbColor
{
unsigned char r;
unsigned char g;
unsigned char b;
} rgbColor;
typedef struct hsvColor
{
unsigned char h;
unsigned char s;
unsigned char v;
} hsvColor;
const int nodesToPixelMap[69] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,
30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61};
@ -21,11 +38,14 @@ const int railsToPixelMap[4][5] = {{70,73,74,77,78},//top positive rail
{71,72,75,76,79},//top negative rail
{69,66,65,62,61},//bottom positive rail
{68,67,64,63,60}};//bottom negative rail
//int nodeColors[MAX_PATHS] = {0};
const int pixelsToRails[20] = {B_RAIL_NEG, B_RAIL_POS, B_RAIL_POS, B_RAIL_NEG, B_RAIL_NEG, B_RAIL_POS, B_RAIL_POS, B_RAIL_NEG, B_RAIL_NEG, B_RAIL_POS,
T_RAIL_POS, T_RAIL_NEG, T_RAIL_NEG, T_RAIL_POS, T_RAIL_POS, T_RAIL_NEG, T_RAIL_NEG, T_RAIL_POS, T_RAIL_POS, T_RAIL_NEG};
extern rgbColor netColors[MAX_NETS];
void initLEDs(void);
void colorWipe(uint32_t color, int wait);
@ -33,4 +53,11 @@ void rainbowy(int ,int, int wait);
void showNets(void);
void assignNetColors (void);
void lightUpNet (int netNumber, int node = -1, int onOff = 1);//-1 means all nodes (default)
hsvColor RgbToHsv(rgbColor rgb);
rgbColor HsvToRgb(hsvColor hsv);
uint32_t packRgb(uint8_t r, uint8_t g, uint8_t b);
#endif

View File

@ -3,6 +3,7 @@
#include <Arduino.h>
#include "JumperlessDefinesRP2040.h"
#include "LEDs.h"
struct netStruct{
@ -13,7 +14,7 @@ const char *name; // human readable "Net 3"
int8_t nodes[MAX_NODES] = {};//maybe make this smaller and allow nets to just stay connected currently 64x64 is 4 Kb
int8_t bridges[MAX_NODES/2][2]; //either store them here or in one long array that references the net
int8_t bridges[MAX_NODES][2]; //either store them here or in one long array that references the net
int8_t specialFunction = -1; // store #defined number for that special function -1 for regular net
@ -23,7 +24,7 @@ int8_t doNotIntersectNodes[8]; //if the net tries to share a node with a net tha
uint8_t priority = 0; //priority = 1 means it will move connections to take the most direct path, priority = 2 means connections will be doubled up when possible, priority = 3 means both
uint32_t color; //color of the net in hex
rgbColor color; //color of the net in hex
};
extern struct netStruct net[MAX_NETS];

View File

@ -12,8 +12,8 @@ int8_t newNode2 = -1;
int foundNode1Net = 0; // netNumbers where that node is, a node can only be in 1 net (except current sense, we'll deal with that separately)
int foundNode2Net = 0; // netNumbers where that node is, a node can only be in 1 net (except current sense, we'll deal with that separately)
//struct pathStruct path[MAX_BRIDGES]; // node1, node2, net, chip[3], x[3], y[3]
int newBridge[MAX_BRIDGES][3]; // node1, node2, net
// struct pathStruct path[MAX_BRIDGES]; // node1, node2, net, chip[3], x[3], y[3]
int newBridge[MAX_BRIDGES][3]; // node1, node2, net
int newBridgeLength = 0;
int newBridgeIndex = 0;
unsigned long timeToNM;
@ -61,7 +61,7 @@ void getNodesToConnect() // read in the nodes you'd like to connect
{
searchExistingNets(newNode1, newNode2);
}
//printBridgeArray();
// printBridgeArray();
newBridgeIndex++; // don't increment this until after the search because we're gonna use it as an index to store the nets
// if (i < 7)
@ -76,7 +76,7 @@ void getNodesToConnect() // read in the nodes you'd like to connect
if (debugNM)
Serial.println("done");
sortPathsByNet();
sortPathsByNet();
}
int searchExistingNets(int node1, int node2) // search through existing nets for all nodes that match either one of the new nodes (so it will be added to that net)
@ -226,7 +226,7 @@ int searchExistingNets(int node1, int node2) // search through existing nets for
void combineNets(int foundNode1Net, int foundNode2Net)
{
if (checkDoNotIntersectsByNet(foundNode1Net, foundNode2Net) == 1)
{
int swap = 0;
@ -314,8 +314,6 @@ void combineNets(int foundNode1Net, int foundNode2Net)
}
}
void deleteNet(int netNumber) // make sure to check special function nets and clear connections to it
{
shiftNets(netNumber);
@ -430,7 +428,7 @@ void addNodeToNet(int netToAddNode, int node)
return;
}
}
net[netToAddNode].nodes[newNodeIndex] = node;
}
@ -486,7 +484,6 @@ int findFirstUnusedNodeIndex(int netNumber) // search for a free net[]
int checkDoNotIntersectsByNet(int netToCheck1, int netToCheck2) // If you're searching DNIs by net, there won't be any valid ways to make a new net with both nodes, so its skipped
{
for (int i = 0; i <= MAX_DNI; i++)
{
@ -519,7 +516,6 @@ int checkDoNotIntersectsByNet(int netToCheck1, int netToCheck2) // If you're sea
Serial.print(" due to Do Not Intersect rules, skipping\n\r");
path[newBridgeIndex].net = -1;
return 0;
}
}
// if(debugNM) Serial.println (" ");
@ -550,7 +546,7 @@ int checkDoNotIntersectsByNet(int netToCheck1, int netToCheck2) // If you're sea
Serial.print(netToCheck1);
if (debugNM)
Serial.print(" due to Do Not Intersect rules, skipping\n\r");
path[newBridgeIndex].net = -1;
path[newBridgeIndex].net = -1;
return 0;
}
}
@ -777,13 +773,11 @@ void listSpecialNets()
void printBridgeArray(void)
{
//Serial.print("\n\n\r");
//Serial.print("newBridgeIndex = ");
//Serial.println(newBridgeIndex);
Serial.print("\n\r");
int tabs = 0;
int lineCount = 0;
for (int i = 0; i < newBridgeLength; i++)
for (int i = 0; i < numberOfPaths; i++)
{
tabs += Serial.print(i);
if (i < 10)
@ -802,11 +796,11 @@ void printBridgeArray(void)
tabs += printNodeOrName(path[i].net);
tabs += Serial.print("],");
lineCount++;
//Serial.print(tabs);
// Serial.print(tabs);
for (int i = 0; i < 24 - (tabs); i++)
{
Serial.print(" ");
}
}
tabs = 0;
if (lineCount == 5)
@ -814,13 +808,17 @@ void printBridgeArray(void)
Serial.print("\n\r");
lineCount = 0;
}
}
if(debugNMtime) Serial.println("\n\r");
if(debugNMtime) timeToNM = millis() - timeToNM;
if(debugNMtime) Serial.print("\n\rtook ");
if(debugNMtime) Serial.print(timeToNM);
if(debugNMtime) Serial.print("ms to run net manager\n\r");
if (debugNMtime)
Serial.println("\n\r");
if (debugNMtime)
timeToNM = millis() - timeToNM;
if (debugNMtime)
Serial.print("\n\rtook ");
if (debugNMtime)
Serial.print(timeToNM);
if (debugNMtime)
Serial.print("ms to run net manager\n\r");
}
int printNodeOrName(int node) // returns number of characters printed (for tabs)
@ -839,7 +837,7 @@ int printNodeOrName(int node) // returns number of characters printed (for tabs)
return Serial.print(node);
}
}
char same[12] = " ";
char same[12] = " ";
const char *definesToChar(int defined) // converts the internally used #defined numbers into human readable strings
{
@ -863,7 +861,7 @@ const char *definesToChar(int defined) // converts the internally used #defined
}
else
{
itoa(defined, same, 10);
return same;
}

View File

@ -29,55 +29,34 @@ unsigned long timeToSort = 0;
bool debugNTCC = false;
bool debugNTCC2 = true;
/*
sort paths by net
find start and end chips - update chipStatus struct there
for each path
find start and end chips
resolve chip candidates
sort chips least to most crowded
assign chips to path
update bbToSfLanes
update chipsLeastToMostCrowded
update sfChipsLeastToMostCrowded
*/
void sortPathsByNet(void) // not actually sorting, just copying the bridges and nets back from netStruct so they're both in the same order
{
timeToSort = micros();
printBridgeArray();
for (int i = 0; i < MAX_BRIDGES; i++)
numberOfNets = 0;
for (int i = 0; i < MAX_NETS; i++)
{
if (net[i].number == 0)
if (net[i].number != 0 && net[i].number != -1)
{
numberOfNets = i;
break;
numberOfNets++;
// break;
}
}
for (int i = 0; i < MAX_BRIDGES; i++)
{
if (path[i].node1 == 0 && path[i].node2 == 0)
if (path[i].node1 != 0 && path[i].node2 != 0)
{
numberOfPaths = i;
break;
numberOfPaths++;
// break;
}
else if (path[i].node1 == 0 && path[i].node2 == 0)
{
// break;
}
}
// printPathArray();
@ -86,15 +65,21 @@ void sortPathsByNet(void) // not actually sorting, just copying the bridges and
Serial.println(numberOfNets);
int pathIndex = 0;
for (int j = 1; j <= numberOfPaths; j++)
for (int j = 1; j <= MAX_NETS; j++)
{
for (int k = 0; k < MAX_BRIDGES; k++)
if (net[j].number == 0)
{
break;
// continue;
}
for (int k = 0; k < MAX_NODES; k++)
{
if (net[j].bridges[k][0] == 0)
{
break;
// continue;
}
else
{
@ -110,16 +95,16 @@ void sortPathsByNet(void) // not actually sorting, just copying the bridges and
numberOfUniqueNets++;
}
// Serial.print("path[");
// Serial.print(pathIndex);
// Serial.print("] net: ");
// Serial.println(path[pathIndex].net);
Serial.print("path[");
Serial.print(pathIndex);
Serial.print("] net: ");
Serial.println(path[pathIndex].net);
pathIndex++;
}
}
}
newBridgeLength = pathIndex;
newBridgeLength = numberOfPaths;
numberOfPaths = pathIndex;
Serial.print("number unique of nets: ");
@ -261,16 +246,16 @@ void commitPaths(void)
Serial.print("xMapL1c1: ");
Serial.println(xMapL1c1);
}
// changed to not stack paths for redundant connections
if ((xMapL1c0 != -1) && ch[path[i].chip[0]].xStatus[xMapL1c0] == path[i].net) // check if lane 1 shares a net first so it should prefer sharing lanes
{
freeLane = 1;
}
else if ((ch[path[i].chip[0]].xStatus[xMapL0c0] == -1) || ch[path[i].chip[0]].xStatus[xMapL0c0] == path[i].net) // lanes will alway be taken together, so only check chip 1
else if ((ch[path[i].chip[0]].xStatus[xMapL0c0] == -1)) // || ch[path[i].chip[0]].xStatus[xMapL0c0] == path[i].net) // lanes will alway be taken together, so only check chip 1
{
freeLane = 0;
}
else if ((xMapL1c0 != -1) && ((ch[path[i].chip[0]].xStatus[xMapL1c0] == -1) || ch[path[i].chip[0]].xStatus[xMapL1c0] == path[i].net))
else if ((xMapL1c0 != -1) && ((ch[path[i].chip[0]].xStatus[xMapL1c0] == -1))) // || ch[path[i].chip[0]].xStatus[xMapL1c0] == path[i].net))
{
freeLane = 1;
}
@ -1564,40 +1549,6 @@ void resolveUncommittedHops(void)
}
else
{
/*
for (int chip = 0; chip < 4; chip++)
{
int freeY = -1;
if (path[i].chip[chip] != -1)
{
for (int freeYsearch = 0; freeYsearch < 8; freeYsearch++)
{
if (ch[path[i].chip[chip]].yStatus[freeYsearch] == -1)
{
freeY = freeYsearch;
break;
}
}
for (int y = 0 ; y< 6; y++)
{
if (path[i].y[y] == -2)
{
path[i].y[y] = freeY;
ch[path[i].chip[chip]].yStatus[freeY] = path[i].net;
}
}
}
}
*/
}
}
@ -2339,7 +2290,7 @@ void printPathArray(void) // this also prints candidates and x y
Serial.print("\n\r");
int tabs = 0;
int lineCount = 0;
for (int i = 0; i < newBridgeLength; i++)
for (int i = 0; i < numberOfPaths; i++)
{
tabs += Serial.print(i);
Serial.print(" ");

View File

@ -6,38 +6,32 @@
#include "FileParsing.h"
#include "NetsToChipConnections.h"
#include "LEDs.h"
#include "CH446Q.h"
// nanoStatus nano;
const char *definesToChar(int); // i really need to find a way to not need to forward declare fuctions with this setup, i hate it
// void printConnections();
void setup()
{
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
initCH446Q();
Serial.begin(115200);
initLEDs();
LittleFS.begin();
delay(3000);
openNodeFile();
initLEDs();
}
void loop()
{
// digitalWrite(LED_BUILTIN,HIGH);
// delay(100);
// digitalWrite(LED_BUILTIN,LOW);
//rainbowy(180, 55, 20); // Red
// delay(800);
getNodesToConnect();
// delay(800);
Serial.println("\n\n\rfinal netlist\n\n\r");
listSpecialNets();
listNets();
@ -45,240 +39,13 @@ void loop()
bridgesToPaths();
assignNetColors();
//rainbowy(180, 55, 20); // Red
while (1);
//rainbowy(180, 55, 20); // Red
// Serial.println("\n\r");
// writeJSONtoFile();
// delay(1000);
/*
for (int i = 0; i < 9; i++) //this is just to check that the structs are being set up correctly
delay(3000);
while (1)
{
Serial.print("\n\r");
Serial.print (net[i].name);
Serial.print ("\t");
Serial.print (net[i].number);
Serial.print ("\t");
Serial.print (definesToChar(net[i].specialFunction));
if (i == 1) Serial.print ("\t"); //padding for "GND"
Serial.print ("\t{");
sendAllPaths();
for (int k = 0; k < 8; k++)
{
if (net[i].doNotIntersectNodes[k] != 0)
{
Serial.print (definesToChar(net[i].doNotIntersectNodes[k]));
Serial.print (",");
}
delay(1200);
}
Serial.print ("}\t");
for (int j = 0 ; j < MAX_NODES; j++)
{
if (net[i].nodes[j] != 0)
{
Serial.print (definesToChar(net[i].nodes[j]));
Serial.print (",");
}
}
Serial.println("\n\n\n\n\r");
}*/
//delay(100);
}
/*
void printConnections(void) {
Serial.println("\n");
Serial.printf("Pin Name\tSF Chip Connections\n\r");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.pinNames[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.pinMap[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.numConns[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.mapI[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xMapI[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xStatusI[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.mapJ[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xMapJ[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xStatusJ[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.mapK[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xMapK[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xStatusK[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.mapL[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xMapL[i]);
Serial.print(" \t");
}
Serial.println(" ");
for (int i = NANO_PIN_D0; i <= NANO_PIN_A7; i++) //just checking if I run out of space
{
Serial.print(nano.xStatusL[i]);
Serial.print(" \t");
}
Serial.println(" ");
Serial.println("\n\n");
*/
/*
Serial.println("\tX connections \t\t\t\t\t\t Y connections");
for (int i = 0; i < 11; i++) //just checking if I run out of space
{
if (i == 8) Serial.println(' ');
Serial.print(mt[i].chipChar);
Serial.print("\t ");
for (int j = 0; j < 16; j++) {
//mt[i].xStatus[j] = -1;
///int ch = (int) mt[i].xMap[j];
if (i < 8) {
Serial.print(mt[mt[i].xMap[j]].chipChar); //here we're using the value of yMap as the index to return chipChar on that chipStatus struct
} else {
switch (mt[i].xMap[j]) {
case GND:
Serial.print("GND");
break;
default:
//Serial.print(mt[i].xMap[j]);
Serial.print(nano.pinNames[nano.reversePinMap[mt[i].xMap[j]]]);
break;
}
}
if (j < 15) Serial.print(", ");
}
Serial.print("\t\t");
if (i > 7) Serial.print(" ");
for (int j = 0; j < 8; j++) {
//chips[i].yStatus[j] = j;
if (mt[i].yMap[j] > 0 && mt[i].yMap[j] < 10) Serial.print(' '); //padding
if (i > 7) {
Serial.print(mt[mt[i].yMap[j]].chipChar);
} else {
Serial.print(mt[i].yMap[j]);
}
if (j < 7) Serial.print(',');
}
Serial.println("\t <- Map");
Serial.print("\t");
for (int j = 0; j < 16; j++) {
//mt[i].xStatus[j] = -1;
if (i > 7) Serial.print(" ");
Serial.print(mt[i].xStatus[j]);
if (mt[i].xStatus[j] > 0 && mt[i].xStatus[j] < 10) Serial.print(' '); //padding
if (i > 7) Serial.print(" ");
if (j < 15) Serial.print(',');
}
Serial.print("\t\t");
for (int j = 0; j < 8; j++) {
//chips[i].yStatus[j] = j;
Serial.print(mt[i].yStatus[j]);
if (mt[i].yStatus[j] > 0 && mt[i].yStatus[j] < 10) Serial.print(' '); //padding
if (j < 7) Serial.print(',');
}
Serial.println("\t <- Status\n");
}
}*/

View File

@ -0,0 +1,68 @@
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pio_spi.h"
// Just 8 bit functions provided here. The PIO program supports any frame size
// 1...32, but the software to do the necessary FIFO shuffling is left as an
// exercise for the reader :)
//
// Likewise we only provide MSB-first here. To do LSB-first, you need to
// - Do shifts when reading from the FIFO, for general case n != 8, 16, 32
// - Do a narrow read at a one halfword or 3 byte offset for n == 16, 8
// in order to get the read data correctly justified.
void __time_critical_func(pio_spi_write8_blocking)(const pio_spi_inst_t *spi, const uint8_t *src, size_t len) {
size_t tx_remain = len, rx_remain = len;
// Do 8 bit accesses on FIFO, so that write data is byte-replicated. This
// gets us the left-justification for free (for MSB-first shift-out)
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
while (tx_remain || rx_remain) {
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
*txfifo = *src++;
--tx_remain;
}
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
(void) *rxfifo;
--rx_remain;
}
}
}
void __time_critical_func(pio_spi_read8_blocking)(const pio_spi_inst_t *spi, uint8_t *dst, size_t len) {
size_t tx_remain = len, rx_remain = len;
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
while (tx_remain || rx_remain) {
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
*txfifo = 0;
--tx_remain;
}
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
*dst++ = *rxfifo;
--rx_remain;
}
}
}
void __time_critical_func(pio_spi_write8_read8_blocking)(const pio_spi_inst_t *spi, uint8_t *src, uint8_t *dst,
size_t len) {
size_t tx_remain = len, rx_remain = len;
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
while (tx_remain || rx_remain) {
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
*txfifo = *src++;
--tx_remain;
}
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
*dst++ = *rxfifo;
--rx_remain;
}
}
}

View File

@ -0,0 +1,24 @@
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PIO_SPI_H
#define _PIO_SPI_H
#include "hardware/pio.h"
#include "spi.pio.h"
typedef struct pio_spi_inst {
PIO pio;
uint sm;
uint cs_pin;
} pio_spi_inst_t;
void pio_spi_write8_blocking(const pio_spi_inst_t *spi, const uint8_t *src, size_t len);
void pio_spi_read8_blocking(const pio_spi_inst_t *spi, uint8_t *dst, size_t len);
void pio_spi_write8_read8_blocking(const pio_spi_inst_t *spi, uint8_t *src, uint8_t *dst, size_t len);
#endif

View File

@ -0,0 +1,268 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
#pragma once
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
// --------- //
// spi_cpha0 //
// --------- //
#define spi_cpha0_wrap_target 0
#define spi_cpha0_wrap 1
static const uint16_t spi_cpha0_program_instructions[] = {
// .wrap_target
0x6101, // 0: out pins, 1 side 0 [1]
0x5101, // 1: in pins, 1 side 1 [1]
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program spi_cpha0_program = {
.instructions = spi_cpha0_program_instructions,
.length = 2,
.origin = -1,
};
static inline pio_sm_config spi_cpha0_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + spi_cpha0_wrap_target, offset + spi_cpha0_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#endif
// --------- //
// spi_cpha1 //
// --------- //
#define spi_cpha1_wrap_target 0
#define spi_cpha1_wrap 2
static const uint16_t spi_cpha1_program_instructions[] = {
// .wrap_target
0x6021, // 0: out x, 1 side 0
0xb101, // 1: mov pins, x side 1 [1]
0x4001, // 2: in pins, 1 side 0
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program spi_cpha1_program = {
.instructions = spi_cpha1_program_instructions,
.length = 3,
.origin = -1,
};
static inline pio_sm_config spi_cpha1_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + spi_cpha1_wrap_target, offset + spi_cpha1_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#include "hardware/gpio.h"
static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits,
float clkdiv, bool cpha, bool cpol, uint pin_sck, uint pin_mosi, uint pin_miso) {
pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(prog_offs) : spi_cpha0_program_get_default_config(prog_offs);
sm_config_set_out_pins(&c, pin_mosi, 1);
sm_config_set_in_pins(&c, pin_miso);
sm_config_set_sideset_pins(&c, pin_sck);
// Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits)
sm_config_set_out_shift(&c, false, true, n_bits);
sm_config_set_in_shift(&c, false, true, n_bits);
sm_config_set_clkdiv(&c, clkdiv);
// MOSI, SCK output are low, MISO is input
pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_sck) | (1u << pin_mosi));
pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_sck) | (1u << pin_mosi), (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
pio_gpio_init(pio, pin_mosi);
pio_gpio_init(pio, pin_miso);
pio_gpio_init(pio, pin_sck);
// The pin muxes can be configured to invert the output (among other things
// and this is a cheesy way to get CPOL=1
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
// SPI is synchronous, so bypass input synchroniser to reduce input delay.
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
pio_sm_init(pio, sm, prog_offs, &c);
pio_sm_set_enabled(pio, sm, true);
}
#endif
// ------------ //
// spi_cpha0_cs //
// ------------ //
#define spi_cpha0_cs_wrap_target 0
#define spi_cpha0_cs_wrap 8
#define spi_cpha0_cs_offset_entry_point 8u
static const uint16_t spi_cpha0_cs_program_instructions[] = {
// .wrap_target
0x6101, // 0: out pins, 1 side 0 [1]
0x4801, // 1: in pins, 1 side 1
0x0840, // 2: jmp x--, 0 side 1
0x6001, // 3: out pins, 1 side 0
0xa022, // 4: mov x, y side 0
0x4801, // 5: in pins, 1 side 1
0x08e0, // 6: jmp !osre, 0 side 1
0xa142, // 7: nop side 0 [1]
0x91e0, // 8: pull ifempty block side 2 [1]
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program spi_cpha0_cs_program = {
.instructions = spi_cpha0_cs_program_instructions,
.length = 9,
.origin = -1,
};
static inline pio_sm_config spi_cpha0_cs_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + spi_cpha0_cs_wrap_target, offset + spi_cpha0_cs_wrap);
sm_config_set_sideset(&c, 2, false, false);
return c;
}
#endif
// ------------ //
// spi_cpha1_cs //
// ------------ //
#define spi_cpha1_cs_wrap_target 0
#define spi_cpha1_cs_wrap 8
#define spi_cpha1_cs_offset_entry_point 7u
static const uint16_t spi_cpha1_cs_program_instructions[] = {
// .wrap_target
0x6901, // 0: out pins, 1 side 1 [1]
0x4001, // 1: in pins, 1 side 0
0x0040, // 2: jmp x--, 0 side 0
0x6801, // 3: out pins, 1 side 1
0xa822, // 4: mov x, y side 1
0x4001, // 5: in pins, 1 side 0
0x00e0, // 6: jmp !osre, 0 side 0
0x91e0, // 7: pull ifempty block side 2 [1]
0xa142, // 8: nop side 0 [1]
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program spi_cpha1_cs_program = {
.instructions = spi_cpha1_cs_program_instructions,
.length = 9,
.origin = -1,
};
static inline pio_sm_config spi_cpha1_cs_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + spi_cpha1_cs_wrap_target, offset + spi_cpha1_cs_wrap);
sm_config_set_sideset(&c, 2, false, false);
return c;
}
#include "hardware/gpio.h"
static inline void pio_spi_cs_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol,
uint pin_sck, uint pin_mosi, uint pin_miso) {
pio_sm_config c = cpha ? spi_cpha1_cs_program_get_default_config(prog_offs) : spi_cpha0_cs_program_get_default_config(prog_offs);
sm_config_set_out_pins(&c, pin_mosi, 1);
sm_config_set_in_pins(&c, pin_miso);
sm_config_set_sideset_pins(&c, pin_sck);
sm_config_set_out_shift(&c, false, true, n_bits);
sm_config_set_in_shift(&c, false, true, n_bits);
sm_config_set_clkdiv(&c, clkdiv);
pio_sm_set_pins_with_mask(pio, sm, (2u << pin_sck), (3u << pin_sck) | (1u << pin_mosi));
pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_sck) | (1u << pin_mosi), (3u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso));
pio_gpio_init(pio, pin_mosi);
pio_gpio_init(pio, pin_miso);
pio_gpio_init(pio, pin_sck);
pio_gpio_init(pio, pin_sck + 1);
gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL);
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
uint entry_point = prog_offs + (cpha ? spi_cpha1_cs_offset_entry_point : spi_cpha0_cs_offset_entry_point);
pio_sm_init(pio, sm, entry_point, &c);
pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2));
pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2));
pio_sm_set_enabled(pio, sm, true);
}
#endif
// ------------------ //
// spi_ch446_multi_cs //
// ------------------ //
#define spi_ch446_multi_cs_wrap_target 0
#define spi_ch446_multi_cs_wrap 9
#define spi_ch446_multi_cs_offset_entry_point 8u
static const uint16_t spi_ch446_multi_cs_program_instructions[] = {
// .wrap_target
0x6201, // 0: out pins, 1 side 0 [2]
0xb242, // 1: nop side 1 [2]
0x1040, // 2: jmp x--, 0 side 1
0x7001, // 3: out pins, 1 side 1
0xb022, // 4: mov x, y side 1
0xd000, // 5: irq nowait 0 side 1
0x3050, // 6: wait 0 irq, 0 rel side 1
0x00e0, // 7: jmp !osre, 0 side 0
0x81e0, // 8: pull ifempty block side 0 [1]
0xa142, // 9: nop side 0 [1]
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program spi_ch446_multi_cs_program = {
.instructions = spi_ch446_multi_cs_program_instructions,
.length = 10,
.origin = -1,
};
static inline pio_sm_config spi_ch446_multi_cs_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + spi_ch446_multi_cs_wrap_target, offset + spi_ch446_multi_cs_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#include "hardware/gpio.h"
static inline void pio_spi_ch446_multi_cs_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol,
uint pin_sck, uint pin_mosi) {
pio_sm_config c = spi_ch446_multi_cs_program_get_default_config(prog_offs);
sm_config_set_out_pins(&c, pin_mosi, 1);
sm_config_set_set_pins(&c, pin_mosi, 1);
sm_config_set_sideset_pins(&c, pin_sck);
sm_config_set_out_shift(&c, false, true, n_bits);
sm_config_set_clkdiv(&c, clkdiv);
pio_sm_set_consecutive_pindirs (pio, sm, pin_sck, 2, true);
pio_gpio_init(pio, pin_mosi);
pio_gpio_init(pio, pin_sck);
//pio_set_irqn_source_enabled (pio,0,pis_sm0_tx_fifo_not_full,true);
// The reason for doing interrupt0 + sm:
// IRQ sources are enabled per irq flag. Since the irq flag being set depends on the state
// machine because of the "0 rel", we want to make sure we're enabling the correct interrupt
// source for the state machine the program is loaded into.
pio_set_irq0_source_enabled(pio, (pio_interrupt_source)(pis_interrupt0 + sm), true);
// Make sure the interrupt starts cleared. It should already be cleared, so this should
// basically be a no-op. I call it defensive programming.
pio_interrupt_clear(pio, sm);
// Build the configuration for the state machine
//pio_set_irq0_source_enabled(pio, pis_interrupt0, true);
irq_set_enabled(PIO0_IRQ_0, true);
uint entry_point = prog_offs;
pio_sm_init(pio, sm, entry_point, &c);
pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2));
pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2));
pio_sm_set_enabled(pio, sm, true);
}
#endif