Ферритовый ROM для самых маленьких

от автора

Готовое устройство
Готовое устройство

И снова здравствуйте, дамы и господа. Наш Отдел Перспективных Разработок продолжает свой цикл статей о древних технологиях и опять выходит на связь с очередным передовым творением нашего сумрачного разума приближающим трепетный момент всеобщей строггофикации.

Сегодня мы совершим небольшой экскурс в историю прошлого века и выдернем оттуда знания об артефакте, практическая пригодность которого на сегодняшний день такова, что перед ней спасует даже наша отдельная лаборатория, которая всем этим поделкам назначение придумывает. В смысле, нулевая практическая пригодность. Однако, вполне сгодится на лабораторную работу для школьника с ардуиной, или занятие на вечер для тебя, мой дорогой инженер с унылой работой, женой, дочкой, двумя котами и кризисом среднего возраста.

Итак, мы рассмотрим память на ферритовых кольцах, причем, даже не RAM, а ROM.

Теория

В ретроспективе компьютерной истории двадцатого века память на ферритовых кольцах стала одной из важных вех развития цифровых технологий. Не смотря на то, что классическое ОЗУ на ферритовых кольцах появилось аж в 1945 году, ПЗУ на похожей технологии в физическом виде реализовали несколько позже, когда понадобилось вместить некоторый объем данных в минимально возможное для технологий того времени пространство. ПЗУ на ферритовых кольцах, оно же «веревочная» память применялась как способ хранения прошивки в виде адресуемых единиц данных, например, в бортовых компьютерах СССР и НАСА того времени, летавшие зондами на Марс и на Луну (миссия «Аполлон» как широко известный пример).

Не смотря на сходный принцип работы ферритовых ОЗУ и ПЗУ, способ хранения информации в них несколько различается. Рассмотрение работы ОЗУ мы оставим для следующих статей, а ПЗУ же функционировало достаточно просто:

Ферритовое кольцо являлось, по сути, примитивнейшим трансформатором, который использовался как датчик наличия тока. Если пропустить через кольцо два проводника и подать через один проводник ток (пусть это будет измеряемый проводник), в кольце наведется магнитный поток, и во втором (измеряющем) проводнике так же возникнет ток, который возможно зафиксировать.

Однако, возникающие напряжения на измеряющем проводнике гораздо ниже, чем на измеряемом, потому, для наших целей мы его немного модифицируем — сделаем несколько витков вокруг кольца и добавим конденсатор и диод. Конденсатор позволит накапливать заряд, стекающий с «измеряющего» проводника, по наличию которого в дальнейшем мы будем принимать решение о наличии тока в «измеряемом» проводнике, а диод позволит не потерять накопленный в конденсаторе заряд.

Ферритовый датчик
Ферритовый датчик

Суть работы данной схемы проста:

Если подать на измеряемый проводник напряжение и считать накопленный конденсатором потенциал с датчика, то, при его наличии можно принять данный факт за установленный бит. Если напряжения нет – бит не установлен.

А теперь магия! Через кольцо возможно пропустить много проводников. Столько, сколько позволит в него запихнуть внутренний диаметр. И, если пометить каждый такой измеряемый проводник адресом, можно судить о наличие отдельного бита по данному адресу.

Экстраполируем данную схему на нашу суровую действительность и попробуем снимать с одного адреса уже не один бит, а целый байт, ибо от одного бита толку мало. Для этого возьмем восемь колец:

Ферритовый байт
Ферритовый байт

Пропустим через кольца проводник, помеченный адресом 0. Поскольку каждое кольцо будет опознавать свой бит, то, через кольца с номером бита, который должен быть установлен в 0, мы просто не будем наш проводник пропускать.

Теперь, если подать напряжение на проводник и читать потенциалы с датчиков колец последовательно, можно составить один байт считанной информации на каждый такой проводник.

Это здорово похоже на запись узелками на веревочках, которую применяли некоторые древние народы, собственно, потому и возник термин «веревочная» память.

Практика

Итак, возьмемся воплощать составленную модель в физическую. Создавать отдельный компьютер под эксплуатирование данного вида памяти мы сегодня не будем и воспользуемся тем, что есть. Я, например, выудил из недр ящика стола очередную ардуину, благо функционала ее для решения нашей задачи хватит с головой.

Во-первых, для считывания потенциала с восьми ферритовых колец нам возможно использовать восемь аналоговых входов (A0 – A7).

Во-вторых, для адресации проводников можно использовать цифровые выводы, коих для небольшого количества адресов вполне хватит.

Впрочем, занимать целый вывод ардуины на один адрес мне показалось расточительным, потому, я еще усложнил схему, применив для адресации выводов сдвиговый регистр из двух 74HC595.

Понимаю, что использование современных микросхем в данном случае несколько «неспортивно», но, построение вот таких вот «гибридов» древних технологий с современными – это особый шик.

В теории, применение сдвигового регистра позволит масштабировать количество адресов памяти не занимая все возможные выводы контроллера, который будет с ними работать, и позволит ему выполнять еще какие-либо задачи. Но, на практике здесь всплывает очередной подводный камень, о котором в конце.

Соберем схему для сдвигового регистра для 16 адресов, который позволит нам адресовать 16 байт:

Схема сдвигового регистра для адресации проводников
Схема сдвигового регистра для адресации проводников

И схему подключения восьми колец на аналоговые пины A0 – A7. Конденсаторы здесь можно взять любые керамические номиналом 100 нФ, диоды так же любые. Я, например, вообще применил что нашел — германиевые 80х годов. Для зрелищности можно попробовать использовать светодиоды. Измеряющая обмотка на кольце – 10 витков любого тонкого провода.

Схема датчика для снятия наличия потенциала с ферритового кольца
Схема датчика для снятия наличия потенциала с ферритового кольца

Так же нужно учесть, что адресные проводники в дальнейшем будут садиться одним концом на землю. Если их все соединить в одной точке, то, при подаче напряжения каждый проводник окажется связан со всеми остальными и сможет вносить помехи в чтение с колец, наводя потенциалы там, где это не нужно. Потому, проводники на землю стоит посадить через диоды. Для наших целей понадобится 16 диодов. Соединение пропускаемых через кольца проводников на землю в данном случае будет выглядеть так:

Схема соединения проводников по адресам
Схема соединения проводников по адресам

Я не заморачивался с травлением и свой вариант на макетной плате спаял проводом МГТФ за вечер. Получилось нечто, что можно лицезреть в первой же картинке данной статьи.

Программирование

Итак, мы можем что-то записать в нашу память. Для этого начнем соединять измеряемые проводники:

Один конец, как упоминалось выше, садится через диод на землю. Затем проводник пропускается последовательно через все ферритовые кольца формируя биты, по принципу — если проводник проходит через кольцо, бит установлен, если проводник не проходит через кольцо, бит не установлен.

После этого второй конец проводника сажается на ножку сдвигового регистра, ассоциированную с адресом данного проводника. Всё, ПЗУ «зашито», причем, в прямом смысле.

Теперь обратимся, наконец, к нашей ардуино и попробуем прочесть то, что мы наделали.

Прошивка ардуино
//Адреса пинов снимающих сигнал с ферритовых колец uint8_t in_pins[8] = {A0, A1, A2, A3, A4, A5, A6, A7};  //Пины управляющие сдвиговым регистром на двух 74HC595 //Пин подключен к ST_CP входу 74HC595 int latchPin = 12; //Пин подключен к SH_CP входу 74HC595 int clockPin = 13; //Пин подключен к DS входу 74HC595 int dataPin = 11;  //Вывод на 16-битный сдвиговый регистр числа, кодирующего пины void shift_out_value(unsigned int val) {   digitalWrite(latchPin, LOW);   //Выведем на сдвиговый регистр последний байт   shiftOut(dataPin, clockPin, MSBFIRST, highByte(val));   //Выведем на сдвиговый регистр первый байт   shiftOut(dataPin, clockPin, MSBFIRST, lowByte(val));   digitalWrite(latchPin, HIGH); }  //Разрядка конденсаторов на датчиках колец void discharge() {   for (int i = 0; i < 8; i++) {     //Переключить пин на выход     pinMode(in_pins[i], OUTPUT);     //занулить     digitalWrite(in_pins[i], LOW);     //небольшая задержка     delay(3);     //Переключить обратно на вход     pinMode(in_pins[i], INPUT);   } }  //Считывание байта с колец uint8_t read_ferrite_byte(unsigned int address) {   uint8_t values[] = {0, 0, 0, 0, 0, 0, 0, 0};    //Для точности можно увеличить количество проходов чтения, но,    //работает и так   //for (uint8_t phase = 0; phase < 2; phase++)   {     //Разрядим     discharge();     //Подергаем нужным проводком по нужному адресу через сдвиговый      //регистр     //Это нужно чтобы создать в ферритовых кольцах магнитный поток и      //зарядить конденсаторы     //на датчиках тех колец, через которые проходит проводник с нужным      //адресом     for (uint8_t j = 0; j < 8; j++) {       shift_out_value(address);       shift_out_value(0);     }     //Считаем показания с датчиков всех колец     for (uint8_t ix = 0; ix < 8; ix++)     {       values[ix] += analogRead(in_pins[ix]);     }   }    discharge();    //Упакуем все считанные значения в один байт, где 0 - не считано    //ничего, 1 - считано что-то   uint8_t result = 0;   for (uint8_t ix = 0; ix < 8; ix++)   {     result = (result << 1) | ((values[ix] > 1) ? 1 : 0);   }   return result; }  void setup() {   pinMode(latchPin, OUTPUT);   pinMode(clockPin, OUTPUT);   pinMode(dataPin, OUTPUT);   for (int i = 0; i < 8; i++) {     pinMode(in_pins[i], INPUT_PULLUP);     digitalWrite(in_pins[i], LOW);   }    Serial.begin(115200);      //разрядим конденсаторы   discharge();   Serial.println("------------------------------");   //Убедимся, что с ферритовых колец ничего не читается   for (uint8_t ix = 0; ix < 8; ix++)   {     Serial.print(analogRead(in_pins[ix]), DEC);     Serial.print(" ");   }    Serial.println();   Serial.println();    //Считаем и выведем значения по адресам 1..16   for (int i = 0; i < 16; i++) {     Serial.print("address[");     if (i < 10) Serial.print("0");     Serial.print( i, DEC);     Serial.print("] = ");     uint8_t nibbles = read_ferrite_byte((unsigned int)1 << i);     Serial.print(nibbles, DEC);     Serial.print(" - ");     Serial.print(nibbles, BIN);     if (nibbles > 32) {       Serial.print(" - ");       Serial.print((char)nibbles);     }     Serial.println();   } }  void loop() { }

Алгоритм чтения следующий:

  1. Разрядить конденсаторы на датчиках ферритовых колец, поскольку, на них мог сохраниться потенциал, оставшийся от предыдущих шагов чтения, и он может внести помехи в читаемые данные.

  2. Задать на адресном регистре адрес ножки, к которой подключен проводник с нужным адресом. При этом, через проводник потечет ток, который вызовет накопление потенциала в конденсаторах датчиков тех колец, через которые пропущен данный проводник.

  3. Снять показание потенциала накопленного заряда со всех колец последовательно по номерам бит в байте и составить считанное значение.

    Результат зависит от того, что было зашито, разумеется.

Зашил слово HELLO и успешно его считал
Зашил слово HELLO и успешно его считал

Ну и подводный камень, о котором я упоминал ранее:

Для наведения магнитного потока в кольцах нужно подавать питание на измеряемые проводники не постоянно, а с определенной частотой. В схеме со сдвиговым регистром для того приходится совершать цикл из нескольких записей адреса и нуля:

  • Записать в регистр адрес пина нужного проводника, тем самым включив его.

  • Записать в регистр 0, выключив все проводники.

  • Повторить N раз.

Если регистр небольшой, скорость записи в него позволит сформировать некоторую частоту подаваемого на проводники тока, позволяющую завести ферритовые кольца и накопить в их датчиках некоторый потенциал.

Если начать увеличивать длину регистра, увеличивая количество адресуемых проводников, скорость записи в регистр так же вырастет, и в какой-то момент частота подаваемого тока уже будет недостаточна для формирования магнитного потока в кольцах.

В таком случае, интересным домашним заданием становится решение подобной задачи масштабирования памяти. Можно попробовать для увеличения количества адресов памяти использовать какую-нибудь каскадную адресацию сдвиговых регистров, где сдвиговый регистр будет ссылаться на следующий сдвиговый регистр. Или использовать логические дешифраторы, повешенные на тот же регистр.

Если у вас в голове родилась интересная схема – поделитесь, а то у меня целый мешок советской логики без дела лежит. ?

UPD: В комментариях предложили использовать ШИМ через ножку OE самого сдвигового регистра, что решает задачу.


ссылка на оригинал статьи https://habr.com/ru/post/687284/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *