AVR ISP adapter (avr109/910 compatible, using ATmega16)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
9.6 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2006 - 2020 by Olaf Rempel *
  3. * razzor AT kopf MINUS tisch DOT de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License, *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <avr/io.h>
  20. #include <string.h>
  21. #include "target.h"
  22. #include "twi_master.h"
  23. #include <util/delay.h>
  24. #if (USE_TWI_SUPPORT)
  25. #define TWI_SLA_W(addr) (addr << 1)
  26. #define TWI_SLA_R(addr) ((addr << 1) | 0x01)
  27. /* ***********************************************************************
  28. * twi_start
  29. * *********************************************************************** */
  30. static uint8_t twi_start(void)
  31. {
  32. TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
  33. loop_until_bit_is_set(TWCR, TWINT);
  34. switch (TWSR & 0xF8)
  35. {
  36. case 0x08: /* START transmitted */
  37. case 0x10: /* repeated START transmitted */
  38. return TWI_SUCCESS;
  39. default:
  40. return TWI_ERROR;
  41. }
  42. } /* twi_start */
  43. /* ***********************************************************************
  44. * twi_stop
  45. * *********************************************************************** */
  46. static void twi_stop(void)
  47. {
  48. TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
  49. } /* twi_stop */
  50. /* ***********************************************************************
  51. * twi_master_tx
  52. * *********************************************************************** */
  53. static uint8_t twi_master_tx(uint8_t value)
  54. {
  55. TWDR = value;
  56. TWCR = (1<<TWINT) | (1<<TWEN);
  57. loop_until_bit_is_set(TWCR, TWINT);
  58. switch (TWSR & 0xF8)
  59. {
  60. case 0x18: /* SLA+W transmitted, ACK received */
  61. case 0x28: /* Data transmitted, ACK received */
  62. case 0x40: /* SLA+R transmitted, ACK received */
  63. return TWI_SUCCESS;
  64. case 0x20: /* SLA+W transmitted, NACK received */
  65. case 0x48: /* SLA+R transmitted, NACK received */
  66. return TWI_NACK_ADDR;
  67. case 0x30: /* Data transmitted, NACK received */
  68. return TWI_NACK_DATA;
  69. default:
  70. return TWI_ERROR;
  71. }
  72. } /* twi_master_tx */
  73. /* ***********************************************************************
  74. * twi_master_rx
  75. * *********************************************************************** */
  76. static uint8_t twi_master_rx(uint8_t * p_value, uint8_t ack)
  77. {
  78. TWCR = (1<<TWINT) | (1<<TWEN) | ((ack) ? (1<<TWEA) : 0x00);
  79. loop_until_bit_is_set(TWCR, TWINT);
  80. *p_value = TWDR;
  81. switch (TWSR & 0xF8)
  82. {
  83. case 0x50: /* Data received, ACK returned */
  84. case 0x58: /* Data received, NAK returned */
  85. return TWI_SUCCESS;
  86. default:
  87. return TWI_ERROR;
  88. }
  89. } /* twi_master_rx */
  90. /* ***********************************************************************
  91. * twi_master_start
  92. * *********************************************************************** */
  93. static uint8_t twi_master_start(uint8_t twi_addr)
  94. {
  95. uint8_t result = TWI_NACK_ADDR;
  96. uint8_t retry = 10;
  97. while ((result == TWI_NACK_ADDR) && (retry--))
  98. {
  99. result = twi_start();
  100. if (result == TWI_SUCCESS)
  101. {
  102. result = twi_master_tx(twi_addr);
  103. if (result == TWI_SUCCESS)
  104. {
  105. return result;
  106. }
  107. }
  108. twi_stop();
  109. _delay_ms(2);
  110. }
  111. return result;
  112. } /* twi_master_start */
  113. /* ***********************************************************************
  114. * twi_master_tx_buf
  115. * *********************************************************************** */
  116. static uint8_t twi_master_tx_buf(const uint8_t * p_data, uint16_t data_size)
  117. {
  118. uint8_t result = TWI_ERROR;
  119. while (data_size--)
  120. {
  121. result = twi_master_tx(*p_data++);
  122. if (result != TWI_SUCCESS)
  123. {
  124. /* NACK for the last transmitted byte is OK */
  125. if ((result == TWI_NACK_DATA) && (data_size == 0))
  126. {
  127. result = TWI_SUCCESS;
  128. }
  129. else
  130. {
  131. break;
  132. }
  133. }
  134. }
  135. return result;
  136. } /* twi_master_tx_buf */
  137. /* ***********************************************************************
  138. * twi_master_rx_buf
  139. * *********************************************************************** */
  140. static uint8_t twi_master_rx_buf(uint8_t * p_data, uint16_t data_size)
  141. {
  142. uint8_t result = TWI_ERROR;
  143. while (data_size--)
  144. {
  145. uint8_t ack;
  146. ack = (data_size > 0);
  147. result = twi_master_rx(p_data++, ack);
  148. if (result != TWI_SUCCESS)
  149. {
  150. break;
  151. }
  152. }
  153. return result;
  154. } /* twi_master_rx_buf */
  155. /* ***********************************************************************
  156. * twi_generic
  157. * *********************************************************************** */
  158. uint8_t twi_generic(uint8_t twi_addr,
  159. const uint8_t * p_wr_data, uint16_t write_size,
  160. uint8_t * p_rd_data, uint16_t read_size)
  161. {
  162. uint8_t result = TWI_ERROR;
  163. if (write_size > 0)
  164. {
  165. result = twi_master_start(TWI_SLA_W(twi_addr));
  166. if (result == TWI_SUCCESS)
  167. {
  168. result = twi_master_tx_buf(p_wr_data, write_size);
  169. }
  170. }
  171. if ((read_size > 0) &&
  172. (result == TWI_SUCCESS)
  173. )
  174. {
  175. result = twi_master_start(TWI_SLA_R(twi_addr));
  176. if (result == TWI_SUCCESS)
  177. {
  178. result = twi_master_rx_buf(p_rd_data, read_size);
  179. }
  180. }
  181. twi_stop();
  182. return result;
  183. } /* twi_generic */
  184. /* ***********************************************************************
  185. * twi_switch_application
  186. * *********************************************************************** */
  187. uint8_t twi_switch_application(uint8_t twi_addr, uint8_t app)
  188. {
  189. uint8_t cmd[2] = { CMD_SWITCH_APPLICATION, app };
  190. return twi_generic(twi_addr, cmd, sizeof(cmd), NULL, 0);
  191. } /* twi_switch_application */
  192. /* ***********************************************************************
  193. * twi_read_version
  194. * *********************************************************************** */
  195. uint8_t twi_read_version(uint8_t twi_addr, char * p_version,
  196. uint8_t version_length)
  197. {
  198. uint8_t cmd[1] = { CMD_READ_VERSION };
  199. return twi_generic(twi_addr, cmd, sizeof(cmd),
  200. (uint8_t *)p_version, version_length);
  201. } /* twi_read_version */
  202. /* ***********************************************************************
  203. * twi_read_chipinfo
  204. * *********************************************************************** */
  205. uint8_t twi_read_chipinfo(uint8_t twi_addr, twi_chipinfo_t * p_chipinfo)
  206. {
  207. uint8_t cmd[4] = { CMD_READ_MEMORY, MEMTYPE_CHIPINFO, 0x00, 0x00 };
  208. return twi_generic(twi_addr, cmd, sizeof(cmd),
  209. (uint8_t *)p_chipinfo, sizeof(twi_chipinfo_t));
  210. } /* twi_read_chipinfo */
  211. /* ***********************************************************************
  212. * twi_read_memory
  213. * *********************************************************************** */
  214. uint8_t twi_read_memory(uint8_t twi_addr, uint8_t memory_type, uint16_t memory_addr,
  215. uint8_t * p_data, uint16_t data_length)
  216. {
  217. uint8_t cmd[4] = { CMD_READ_MEMORY, memory_type,
  218. (memory_addr >> 8) & 0xFF,
  219. (memory_addr & 0xFF) };
  220. return twi_generic(twi_addr, cmd, sizeof(cmd), p_data, data_length);
  221. } /* twi_read_memory */
  222. /* ***********************************************************************
  223. * twi_write_memory
  224. * *********************************************************************** */
  225. uint8_t twi_write_memory(uint8_t twi_addr, uint8_t memory_type, uint16_t memory_addr,
  226. const uint8_t * p_data, uint16_t data_length)
  227. {
  228. uint8_t cmd[4] = { CMD_WRITE_MEMORY, memory_type,
  229. (memory_addr >> 8) & 0xFF,
  230. (memory_addr & 0xFF) };
  231. uint8_t result;
  232. result = twi_master_start(TWI_SLA_W(twi_addr));
  233. if (result == TWI_SUCCESS)
  234. {
  235. result = twi_master_tx_buf(cmd, sizeof(cmd));
  236. }
  237. if (result == TWI_SUCCESS)
  238. {
  239. result = twi_master_tx_buf(p_data, data_length);
  240. }
  241. twi_stop();
  242. return result;
  243. } /* twi_read_memory */
  244. /* ***********************************************************************
  245. * twi_init
  246. * *********************************************************************** */
  247. void twi_init(uint8_t enable)
  248. {
  249. if (enable)
  250. {
  251. TWBR = ((F_CPU / 100000) -16) / 2;
  252. TWCR = (1<<TWSTO) | (1<<TWEN);
  253. }
  254. else
  255. {
  256. TWCR = 0x00;
  257. }
  258. } /* twi_init */
  259. #endif /* (USE_TWI_SUPPORT) */