Write performance improvements.
[SCSI2SD-V6.git] / software / SCSI2SD / SCSI2SD.cydsn / loopback.c
1 //      Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\r
2 //\r
3 //      This file is part of SCSI2SD.\r
4 //\r
5 //      SCSI2SD is free software: you can redistribute it and/or modify\r
6 //      it under the terms of the GNU General Public License as published by\r
7 //      the Free Software Foundation, either version 3 of the License, or\r
8 //      (at your option) any later version.\r
9 //\r
10 //      SCSI2SD is distributed in the hope that it will be useful,\r
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 //      GNU General Public License for more details.\r
14 //\r
15 //      You should have received a copy of the GNU General Public License\r
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 #include "loopback.h"\r
19 #include "scsi.h"\r
20 #include "device.h"\r
21 \r
22 // Return true if all inputs are un-asserted (1)\r
23 // Note that CyPins returns non-zero if pin is active. It does NOT\r
24 // necessarily return 1.\r
25 static int test_initial_inputs(void)\r
26 {\r
27         uint8 dbx = SCSI_In_DBx_Read();\r
28         int result =\r
29                 (dbx == 0xFF) &&\r
30                 CyPins_ReadPin(SCSI_In_DBP) &&\r
31                 CyPins_ReadPin(SCSI_ATN_INT) &&\r
32                 CyPins_ReadPin(SCSI_In_BSY)     &&\r
33                 CyPins_ReadPin(SCSI_In_ACK) &&\r
34                 CyPins_ReadPin(SCSI_RST_INT) &&\r
35                 CyPins_ReadPin(SCSI_In_MSG) &&\r
36                 CyPins_ReadPin(SCSI_In_SEL) &&\r
37                 CyPins_ReadPin(SCSI_In_CD) &&\r
38                 CyPins_ReadPin(SCSI_In_REQ) &&\r
39                 CyPins_ReadPin(SCSI_In_IO);\r
40 \r
41         return result;\r
42 }\r
43 \r
44 static int test_data_lines(void)\r
45 {\r
46         int result = 1;\r
47         int i;\r
48         for (i = 0; i < 8; ++i)\r
49         {\r
50                 // We write using Active High\r
51                 SCSI_Out_DBx_Write(1 << i);\r
52                 CyDelay(1); // ms\r
53                 \r
54                 // And expect an Active Low response.\r
55                 uint8 dbx = SCSI_In_DBx_Read();\r
56                 result = result && (dbx == (0xFF ^ (1 << i)));\r
57         }\r
58         SCSI_Out_DBx_Write(0);\r
59         return result;\r
60 }\r
61 \r
62 static int test_data_10MHz(void)\r
63 {\r
64         // 10MHz = 100ns period.\r
65         // We'll try and go high -> low -> high in 100ns.\r
66         // At 66MHz, 50ns ~= 3 cycles.\r
67         \r
68         int result = 1;\r
69         int i;\r
70         for (i = 0; i < 100; ++i)\r
71         {\r
72                 // We write using Active High\r
73                 SCSI_Out_DBx_Write(0xFF);\r
74                 CyDelayCycles(3);\r
75                 // And expect an Active Low response.\r
76                 uint8 dbx = SCSI_In_DBx_Read();\r
77                 result = result && (dbx == 0);\r
78                 \r
79                 // We write using Active High\r
80                 SCSI_Out_DBx_Write(0);\r
81                 CyDelayCycles(3);\r
82                 // And expect an Active Low response.\r
83                 dbx = SCSI_In_DBx_Read();\r
84                 result = result && (dbx == 0xFF);\r
85         }\r
86         SCSI_Out_DBx_Write(0);\r
87         return result;\r
88 }\r
89 \r
90 static int test_ATN_interrupt(void)\r
91 {\r
92         int result = 1;\r
93         int i;\r
94         \r
95         scsiDev.atnFlag = 0;\r
96         for (i = 0; i < 100 && result; ++i)\r
97         {\r
98                 // We write using Active High\r
99                 CyPins_SetPin(SCSI_Out_ATN);\r
100                 CyDelayCycles(2);\r
101                 result &= scsiDev.atnFlag == 1;\r
102                 scsiDev.atnFlag = 0;\r
103                 CyPins_ClearPin(SCSI_Out_ATN);\r
104                 result &= scsiDev.atnFlag == 0;\r
105         }\r
106         return result;\r
107 }\r
108 \r
109 static void test_error(void)\r
110 {\r
111         // Toggle LED.\r
112         while (1)\r
113         {\r
114                 LED1_Write(0);\r
115                 CyDelay(250); // ms\r
116                 LED1_Write(1);\r
117                 CyDelay(250); // ms\r
118         }\r
119 }\r
120 \r
121 static void test_success(void)\r
122 {\r
123         // Toggle LED.\r
124         while (1)\r
125         {\r
126                 LED1_Write(0);\r
127                 CyDelay(1000); // ms\r
128                 LED1_Write(1);\r
129                 CyDelay(1000); // ms\r
130         }\r
131 }\r
132 void scsi2sd_test_loopback(void)\r
133 {\r
134         if (!test_initial_inputs() ||\r
135                 !test_data_lines() ||\r
136                 !test_data_10MHz() ||\r
137                 !test_ATN_interrupt())\r
138         {\r
139                 test_error();\r
140         }\r
141         else\r
142         {\r
143                 test_success();\r
144         }\r
145 }