Код:
/*
* SD-картридер подключяется к выводам ардуино:
** MOSI - D11
** MISO - D12
** CLK - D13
** CS - D10
*
* Выход - D3
*/
#include <SdFat.h>
SdFat sd;
SdFile romFile;
// Заголовок
byte SB[27] = {
0x4E, 0x4F, 0x44, 0x49, 0x53, 0x43, 0x30, 0x30, // NODISK00
0x31, 0x34, 0x30, 0x32, 0x31, 0x38, // дата: 140218
0x74, 0x65, 0x73, 0x74, 0x74, 0x70, 0x20, 0x20, // testtp.....
0x20, 0x20, 0x20, 0x00, 0x00 };
int p = 3; // номер пина, на который будет вывод сигнала
unsigned long Tzd = 0; // переменная для расчёта задержки
const int Tpp = 256; // Длительность задержки сигнала в микросекундах (один полупериод)
void setup() //процедура setup
{
pinMode(p, OUTPUT); //объявляем пин как выход
pinMode(10, OUTPUT);
while (!sd.begin(10,SPI_FULL_SPEED)){ // SD-карта готова?
tone(p, 200, 100); // нет -- включаем на 200 Гц на 100 мс
delay(3000); // ждем 3 с
}
sd.chdir(); // устанавливаем корневую директорию SD
}
void loop() //процедура loop
{
tone(p, 500, 100); //включаем на 500 Гц на 100 мс
delay(1000); //ждем 1 с
if (romFile.open("cybernoi.rom",O_READ)) { // открываем файл. Открылся?
byte BLs = 0x01; // начальный блок
unsigned int Nbt = romFile.fileSize(); // всего байт
byte BLe = Nbt/256; // всего блоков
byte BLt; // осталось блоков
byte Nst; // номер строки
byte St; // выводимый байт
byte CSz = 0x00; // контрольная сумма заголовка
byte CSs = 0x00; // контрольная сумма строки
byte i;
byte j;
if (Nbt%256 != 0){ // корректировка количества блоков, если размер файла не кратен 256
BLe++;
}
// Начинаем вывод
for (i=0; i<=3; i++){ // преамбула (4*(00H*25+55H*25))
for (j=0; j<=24; j++){
SendByte(0x00);
}
for (j=0; j<=24; j++){
SendByte(0x55);
}
}
for (BLt=BLe; BLt>=1; BLt--){ // Вывод блоков данных
CSz = BLs;
CSz += BLe;
CSz += BLt;
// упреждающее чтение первого байта блока данных с карты (он всегда есть)
St = romFile.read(); // читаем байт из файла
Nbt--;
for (j=0; j<=15; j++){ // 00h*16
SendByte(0x00);
}
for (j=0; j<=3; j++){ // 55h*4
SendByte(0x55);
}
SendByte(0xE6); // E6h*1
for (j=0; j<=3; j++){ // 00h*4
SendByte(0x00);
}
for (j=0; j<=26; j++){ // заголовок блока
CSz += SB[j];
SendByte(SB[j]);
}
SendByte(BLs); // начальный блок
SendByte(BLe); // конечный блок
SendByte(BLt); // осталось блоков
SendByte(CSz); // контр.сумма заголовка
for (Nst=0x80; Nst<=0x87; Nst++){ // вывод строк (8 шт.)
for (j=0; j<=3; j++){ // 00h*4
SendByte(0x00);
}
SendByte(0xE6); // E6h*1
CSs = Nst;
SendByte(Nst); // номер строки
CSs += CSz;
SendByte(CSz); // контр.сумма заголовка
CSs += St; // начинаем вывод строки данных
SendByte(St); // предварительно считанный байт
for (j=0; j<=30; j++){ // остальные 31 байт
if (Nbt > 0){ // ещё есть данные?
St = romFile.read(); // читаем очередной байт из файла
Nbt--;
}
else { // нет -- дополняем нулями
St = 0x00;
}
SendByte(St); // передаём считанный байт
CSs += St;
}
SendByte(CSs); // контр.сумма строки
if (Nst !=0x87) {
if (Nbt > 0){ // ещё есть данные?
St = romFile.read(); // читаем очередной байт из файла
Nbt--;
}
else { // нет -- дополняем нулями
St = 0x00;
}
}
}
}
for (j=0; j<=15; j++){ // 00h*16 -- завершение вывода программы (?)
SendByte(0x00);
}
// close the file:
romFile.close();
}
else {
tone(p, 200, 300); // нет файла -- включаем на 200 Гц на 300 мс
}
delay(15000); // ждем 15 с
}
void SendByte(byte SBt){ // Подпрограмма вывода байта
byte Pd=PORTD;
byte i=8;
do{ // Выводим биты начиная со старшего
i--;
Tzd = micros() - Tzd; // Вычисляем, какая была задержка
if (Tzd < Tpp) { // Если прошло времени меньше, чем установленная задержка
delayMicroseconds(Tpp - Tzd); // Задержка второго полупериода сигнала (предыдущего)
}
Pd ^= (1 << p); // инвертируем бит в позиции p(=3)
PORTD = Pd; // вывод в порт p
delayMicroseconds(Tpp); // Задержка первого полупериода сигнала
Tzd = micros(); // начало отсчёта длительности задержки
if ((bitRead(Pd, p))^(bitRead(SBt, i))){ // Если состояние порта и выводимый бит разные
Pd ^= (1 << p); // инвертируем бит в позиции p
PORTD = Pd; // вывод в порт p
}
}
while (i>0);
}